v416
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package chihane.jdaddressselector;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
|
||||
public class BottomDialog extends Dialog {
|
||||
private Selector selector;
|
||||
|
||||
public BottomDialog(Context context) {
|
||||
super(context, R.style.bottom_dialog);
|
||||
}
|
||||
|
||||
public BottomDialog(Context context, int themeResId) {
|
||||
super(context, themeResId);
|
||||
}
|
||||
|
||||
public BottomDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
|
||||
super(context, cancelable, cancelListener);
|
||||
}
|
||||
|
||||
public void init(Context context,Selector selector) {
|
||||
this.selector = selector;
|
||||
setContentView(selector.getView());
|
||||
Window window = getWindow();
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
params.height = dip2px(context, 256);
|
||||
window.setAttributes(params);
|
||||
|
||||
window.setGravity(Gravity.BOTTOM);
|
||||
}
|
||||
|
||||
public static int dip2px(Context context, float dpValue) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
public void setOnAddressSelectedListener(SelectedListener listener) {
|
||||
this.selector.setSelectedListener(listener);
|
||||
}
|
||||
|
||||
public static BottomDialog show(Context context) {
|
||||
return show(context, null);
|
||||
}
|
||||
|
||||
public static BottomDialog show(Context context, SelectedListener listener) {
|
||||
BottomDialog dialog = new BottomDialog(context, R.style.bottom_dialog);
|
||||
dialog.selector.setSelectedListener(listener);
|
||||
dialog.show();
|
||||
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package chihane.jdaddressselector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by dun on 17/2/9.
|
||||
*/
|
||||
|
||||
public interface DataProvider {
|
||||
void provideData(int currentDeep,int preId,DataReceiver receiver);
|
||||
|
||||
|
||||
interface DataReceiver {
|
||||
void send(List<ISelectAble> data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package chihane.jdaddressselector;
|
||||
|
||||
/**
|
||||
* Created by dun on 17/2/9.
|
||||
*/
|
||||
|
||||
public interface ISelectAble {
|
||||
/**
|
||||
* 显示在栏目上的名字
|
||||
* */
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* 用户设定的id,根据这个id,可以获取级栏目或者指定为最终栏目的id
|
||||
* */
|
||||
public int getId();
|
||||
public String getUuid();
|
||||
/**
|
||||
* 自定义类型对象。
|
||||
* */
|
||||
public String county_name();
|
||||
public String city_name();
|
||||
public String prov_name();;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package chihane.jdaddressselector;
|
||||
|
||||
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 java.util.List;
|
||||
|
||||
/**
|
||||
* Created by dun on 17/2/9.
|
||||
*/
|
||||
|
||||
public class SelectAdapter extends BaseAdapter{
|
||||
List<ISelectAble> datas;
|
||||
int selectedIndex = Selector.INDEX_INVALID;
|
||||
public SelectAdapter(List<ISelectAble> datas) {
|
||||
this.datas = datas;
|
||||
}
|
||||
|
||||
public void setSelectedIndex(int selectedIndex) {
|
||||
this.selectedIndex = selectedIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return datas.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return datas.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return datas.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.item_area, parent, false);
|
||||
|
||||
holder = new Holder();
|
||||
holder.textView = (TextView) convertView.findViewById(R.id.textView);
|
||||
holder.imageViewCheckMark = (ImageView) convertView.findViewById(R.id.imageViewCheckMark);
|
||||
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (Holder) convertView.getTag();
|
||||
}
|
||||
|
||||
ISelectAble item = (ISelectAble) getItem(position);
|
||||
holder.textView.setText(item.getName());
|
||||
|
||||
boolean checked = selectedIndex != Selector.INDEX_INVALID && datas.get(selectedIndex).getId() == item.getId();
|
||||
holder.textView.setEnabled(!checked);
|
||||
holder.imageViewCheckMark.setVisibility(checked ? View.VISIBLE : View.GONE);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
class Holder {
|
||||
TextView textView;
|
||||
ImageView imageViewCheckMark;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package chihane.jdaddressselector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
public interface SelectedListener {
|
||||
/**
|
||||
* 回调接口,根据选择深度,按顺序返回选择的对象。
|
||||
* */
|
||||
void onAddressSelected(ArrayList<ISelectAble> selectAbles);
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
package chihane.jdaddressselector;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Selector implements AdapterView.OnItemClickListener {
|
||||
|
||||
public static final int INDEX_INVALID = -1;
|
||||
private final Context context;
|
||||
private SelectedListener listener;
|
||||
private View view;
|
||||
private View indicator;
|
||||
private LinearLayout ll_tabLayout;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
private ListView listView;
|
||||
|
||||
|
||||
private int tabIndex = 0;
|
||||
|
||||
|
||||
/* 每个tab的adapter */ List<List<ISelectAble>> allDatas = new ArrayList<>();
|
||||
private SelectAdapter[] adapters;
|
||||
/*选择的深度*/
|
||||
private int selectDeep;
|
||||
private int[] selectedIndex;
|
||||
|
||||
DataProvider dataProvider;
|
||||
|
||||
public void setDataProvider(DataProvider dataProvider) {
|
||||
this.dataProvider = dataProvider;
|
||||
getNextData(0);
|
||||
}
|
||||
|
||||
public Selector(Context context, int deep) {
|
||||
this.context = context;
|
||||
this.allDatas = new ArrayList<>(deep);
|
||||
selectedIndex = new int[deep];
|
||||
this.selectDeep = deep;
|
||||
for (int i = 0; i < deep; i++) {
|
||||
allDatas.add(new ArrayList<ISelectAble>());
|
||||
}
|
||||
initAdapters();
|
||||
initViews();
|
||||
}
|
||||
|
||||
private void initAdapters() {
|
||||
adapters = new SelectAdapter[allDatas.size()];
|
||||
for (int i = 0; i < selectDeep; i++) {
|
||||
adapters[i] = new SelectAdapter(allDatas.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
private TextView[] tabs;
|
||||
|
||||
private void initViews() {
|
||||
view = LayoutInflater.from(context).inflate(R.layout.address_selector, null);
|
||||
|
||||
this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
|
||||
|
||||
this.listView = (ListView) view.findViewById(R.id.listView);
|
||||
this.indicator = view.findViewById(R.id.indicator);
|
||||
this.ll_tabLayout = (LinearLayout) view.findViewById(R.id.layout_tab);
|
||||
tabs = new TextView[allDatas.size()];
|
||||
for (int i = 0; i < allDatas.size(); i++) {
|
||||
//动态新增TextView
|
||||
TextView textView = (TextView) LayoutInflater.from(context).inflate(R.layout.simple_text_view, ll_tabLayout, false);
|
||||
ll_tabLayout.addView(textView);
|
||||
//绑定TextView的点击事件
|
||||
final int finalI = i;
|
||||
textView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//设置tab 下标
|
||||
tabIndex = finalI + 1;
|
||||
//更新adapter
|
||||
listView.setAdapter(adapters[finalI]);
|
||||
//设置选择位置
|
||||
if (selectedIndex[finalI] != INDEX_INVALID) {
|
||||
listView.setSelection(selectedIndex[finalI]);
|
||||
}
|
||||
updateTabsVisibility(tabIndex-1);
|
||||
updateIndicator(tabIndex - 1);
|
||||
}
|
||||
});
|
||||
tabs[i] = textView;
|
||||
}
|
||||
|
||||
|
||||
this.listView.setOnItemClickListener(this);
|
||||
|
||||
updateIndicator(tabIndex);
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 指示器动画
|
||||
*/
|
||||
private void updateIndicator(final int tabIndex) {
|
||||
view.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
buildIndicatorAnimatorTowards(tabs[tabIndex]).start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private AnimatorSet buildIndicatorAnimatorTowards(TextView tab) {
|
||||
ObjectAnimator xAnimator = ObjectAnimator.ofFloat(indicator, "X", indicator.getX(), tab.getX());
|
||||
|
||||
final ViewGroup.LayoutParams params = indicator.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();
|
||||
indicator.setLayoutParams(params);
|
||||
}
|
||||
});
|
||||
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.setInterpolator(new FastOutSlowInInterpolator());
|
||||
set.playTogether(xAnimator, widthAnimator);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
|
||||
private void updateTabsVisibility(int index) {
|
||||
for (int i = 0; i < tabs.length; i++) {
|
||||
TextView tv = tabs[i];
|
||||
tv.setVisibility(allDatas.get(i).size() != 0 ? View.VISIBLE : View.GONE);
|
||||
tv.setEnabled(index != i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
this.selectedIndex[tabIndex - 1] = position;
|
||||
|
||||
|
||||
ISelectAble selectAble = allDatas.get(tabIndex - 1).get(position);
|
||||
tabs[tabIndex-1].setText(selectAble.getName());
|
||||
for (int i = tabIndex; i < this.allDatas.size(); i++) {
|
||||
tabs[i].setText("请选择");
|
||||
allDatas.get(i).clear();
|
||||
adapters[i].setSelectedIndex(-1);
|
||||
adapters[i].notifyDataSetChanged();
|
||||
this.selectedIndex[i] = INDEX_INVALID;
|
||||
}
|
||||
this.adapters[tabIndex - 1].setSelectedIndex(position);
|
||||
this.adapters[tabIndex - 1].notifyDataSetChanged();
|
||||
// if(tabIndex == selectDeep-1)
|
||||
// {
|
||||
// callbackInternalno();
|
||||
// }
|
||||
if (tabIndex == selectDeep) {
|
||||
callbackInternal();
|
||||
return;
|
||||
}
|
||||
updateTabsVisibility(tabIndex -1);
|
||||
updateIndicator(tabIndex);
|
||||
getNextData(selectAble.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前集合选择的id,向用户获取下一级子集的数据
|
||||
*/
|
||||
private void getNextData(int preId) {
|
||||
if (dataProvider == null) {
|
||||
return;
|
||||
}
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
dataProvider.provideData(tabIndex, preId, new DataProvider.DataReceiver() {
|
||||
@Override
|
||||
public void send(List<ISelectAble> data) {
|
||||
if (data.size() > 0) {
|
||||
//更新当前tab下标
|
||||
allDatas.get(tabIndex).clear();
|
||||
allDatas.get(tabIndex).addAll(data);
|
||||
adapters[tabIndex].notifyDataSetChanged();
|
||||
listView.setAdapter(adapters[tabIndex]);
|
||||
} else {
|
||||
//次级没有内容,直接回调
|
||||
callbackInternal();
|
||||
}
|
||||
|
||||
updateTabsVisibility(tabIndex);
|
||||
updateProgressVisibility();
|
||||
updateIndicator(tabIndex);
|
||||
tabIndex = tabIndex + 1 >= selectDeep ? selectDeep : tabIndex + 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void callbackInternal() {
|
||||
if (listener != null) {
|
||||
|
||||
ArrayList<ISelectAble> result = new ArrayList<>(allDatas.size());
|
||||
for (int i = 0; i < selectDeep; i++) {
|
||||
ISelectAble resultBean = allDatas.get(i) == null
|
||||
|| selectedIndex[i] == INDEX_INVALID ? null : allDatas.get(i).get(selectedIndex[i]);
|
||||
result.add(resultBean);
|
||||
}
|
||||
listener.onAddressSelected(result);
|
||||
}
|
||||
}
|
||||
private void callbackInternalno() {
|
||||
if (listener != null) {
|
||||
|
||||
ArrayList<ISelectAble> result = new ArrayList<>(allDatas.size()-1);
|
||||
for (int i = 0; i < selectDeep-1; i++) {
|
||||
ISelectAble resultBean = allDatas.get(i) == null
|
||||
|| selectedIndex[i] == INDEX_INVALID ? null : allDatas.get(i).get(selectedIndex[i]);
|
||||
result.add(resultBean);
|
||||
}
|
||||
listener.onAddressSelected(result);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateProgressVisibility() {
|
||||
ListAdapter adapter = listView.getAdapter();
|
||||
int itemCount = adapter.getCount();
|
||||
progressBar.setVisibility(itemCount > 0 ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
|
||||
public SelectedListener getOnAddressSelectedListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
public void setSelectedListener(SelectedListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package chihane.jdaddressselector.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ListView;
|
||||
|
||||
public class UninterceptableListView extends ListView {
|
||||
public UninterceptableListView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public UninterceptableListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public UninterceptableListView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
return super.onTouchEvent(ev);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user