Android 仿ios 实现地址选择

//  滚轮控件的RecycleView
public class WheelRecyclerView extends RecyclerView {

    //默认参数
    private final int DEFAULT_WIDTH = Util.dp2px(160);

    private final int DEFAULT_ITEM_HEIGHT = Util.dp2px(50);

    private final int DEFAULT_SELECT_TEXT_COLOR = Color.BLACK;

    private final int DEFAULT_UNSELECT_TEXT_COLOR = getResources().getColor(R.color.color136);

    private final int DEFAULT_SELECT_TEXT_SIZE = Util.sp2px(14);

    private final int DEFAULT_UNSELECT_TEXT_SIZE = Util.sp2px(14);

    private final int DEFAULT_OFFSET = 1;

    private final int DEFAULT_DIVIDER_WIDTH = ViewGroup.LayoutParams.MATCH_PARENT;

    private final int DEFAULT_DIVIDER_HEIGHT = Util.dp2px(1);

    private final int DEFAULT_DIVIVER_COLOR = getResources().getColor(R.color.color136);


    private WheelAdapter mAdapter;

    private LinearLayoutManager mLayoutManager;

    private List<String> mDatas; //数据

    private int mItemHeight; //选项高度

    private int mOffset; //处于中间的item为选中,在头尾需补充 offset个空白view,可显示的item数量=2*offset+1

    private int mSelectTextColor; //选中item的文本颜色

    private int mUnselectTextColor; //非选中item的文本颜色

    private float mSelectTextSize; //选中item的文本大小

    private float mUnselectTextSize;//非选中item的文本大小

    private float mDividerWidth;//分割线的宽度

    private float mDividerHeight;//分割线高度

    private int mDividerColor;//分割线颜色

    private Paint mPaint;//绘制分割线的paint

    private OnSelectListener mOnSelectListener;

    private int mSelected;
    private Context mContext;

    public WheelRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WheelRecyclerView);

        mItemHeight = (int) ta.getDimension(R.styleable.WheelRecyclerView_itemHeight, DEFAULT_ITEM_HEIGHT);
        mSelectTextColor = ta.getColor(R.styleable.WheelRecyclerView_selectTextColor, DEFAULT_SELECT_TEXT_COLOR);
        mUnselectTextColor = ta.getColor(R.styleable.WheelRecyclerView_unselectTextColor, DEFAULT_UNSELECT_TEXT_COLOR);
        mSelectTextSize = ta.getDimension(R.styleable.WheelRecyclerView_selectTextSize, DEFAULT_SELECT_TEXT_SIZE);
        mUnselectTextSize = ta.getDimension(R.styleable.WheelRecyclerView_unselectTextSize, DEFAULT_UNSELECT_TEXT_SIZE);
        mOffset = ta.getInteger(R.styleable.WheelRecyclerView_wheelOffset, DEFAULT_OFFSET);
        mDividerWidth = ta.getDimension(R.styleable.WheelRecyclerView_dividerWidth, DEFAULT_DIVIDER_WIDTH);
        mDividerHeight = ta.getDimension(R.styleable.WheelRecyclerView_dividerHeight, DEFAULT_DIVIDER_HEIGHT);
        mDividerColor = ta.getColor(R.styleable.WheelRecyclerView_dividerColor, DEFAULT_DIVIVER_COLOR);

        ta.recycle();

        mDatas = new ArrayList<>();
        mPaint = new Paint();
        mPaint.setColor(mDividerColor);
        mPaint.setStrokeWidth(mDividerHeight);

        init();
    }

    private void init() {
        mLayoutManager = new LinearLayoutManager(getContext());
        setLayoutManager(mLayoutManager);
        if (mDividerColor != Color.TRANSPARENT && mDividerHeight != 0 && mDividerWidth != 0) {
            addItemDecoration(new DividerItemDecoration());
        }
        mAdapter = new WheelAdapter();
        setAdapter(mAdapter);
        addOnScrollListener(new OnWheelScrollListener());

    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        int width;
        int height;
        int heightSpecSize = MeasureSpec.getSize(heightSpec);
        int heightSpecMode = MeasureSpec.getMode(heightSpec);
        //当指定了控件高度时,每个item平分整个高度,控件无指定高度时,默认高度为可视item的累加高度
        switch (heightSpecMode) {
            case MeasureSpec.EXACTLY:
                height = heightSpecSize;
                mItemHeight = height / (mOffset * 2 + 1);
                break;
            default:
                height = (mOffset * 2 + 1) * mItemHeight;
                break;
        }
        width = getDefaultSize(DEFAULT_WIDTH, widthSpec);
        if (mDividerWidth == DEFAULT_DIVIDER_WIDTH) {
            mDividerWidth = width;
        }
        setMeasuredDimension(width, height);
    }

    public void setData(List<String> datas) {
        if (datas == null) {
            return;
        }
        mDatas.clear();
        mDatas.addAll(datas);
        mAdapter.notifyDataSetChanged();
        setSelect(0);
        scrollTo(0,0);
    }

    public void setOnSelectListener(OnSelectListener listener) {
        mOnSelectListener = listener;
    }

    public void setSelect(int position) {
        mSelected = position;
        mLayoutManager.scrollToPosition(mSelected);
    }

    public int getSelected() {
        return mSelected;
    }

    private class WheelAdapter extends Adapter<WheelAdapter.WheelHolder> {

        // 动画转变线
        private float mTurningLine;
        // Recyclerview视图
        private RecyclerView mParentView;

        @Override
        public WheelHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            mParentView = (RecyclerView) parent;
            // 以recyclerview中等高度水平线作为动画转变的标准
            mTurningLine = 300;

            WheelHolder holder = new WheelHolder(LayoutInflater.from(getContext()).inflate(R.layout.item_wheel, parent, false));
            holder.name.getLayoutParams().height = mItemHeight;
            return holder;
        }

        @Override
        public int getItemCount() {
            return mDatas.size() == 0 ? 0 : mDatas.size() + mOffset * 2;
        }

        @Override
        public void onBindViewHolder(WheelHolder holder, int position) {
            //头尾填充offset个空白view以使数据能处于中间选中状态
            if (position < mOffset || position > mDatas.size() + mOffset - 1) {
                holder.name.setText("");
            } else {
                holder.name.setText(mDatas.get(position - mOffset));
            }


        }

        class WheelHolder extends ViewHolder {
            // 视图容器
            private ViewGroup containerView;
            TextView name;
            // 子项顶部所在的位置(像素点)
            private float itemTop = Integer.MIN_VALUE;

            public WheelHolder(View itemView) {
                super(itemView);
                name = (TextView) itemView.findViewById(R.id.tv_name);
            }
        }
    }

    private class OnWheelScrollListener extends OnScrollListener {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                //当控件停止滚动时,获取可视范围第一个item的位置,滚动调整控件以使选中的item刚好处于正中间
                int firstVisiblePos = mLayoutManager.findFirstVisibleItemPosition();
                if (firstVisiblePos == RecyclerView.NO_POSITION) {
                    return;
                }
                Rect rect = new Rect();
                mLayoutManager.findViewByPosition(firstVisiblePos).getHitRect(rect);
                if (Math.abs(rect.top) > mItemHeight / 2) {
                    smoothScrollBy(0, rect.bottom);
                    mSelected = firstVisiblePos + 1;

                } else {
                    smoothScrollBy(0, rect.top);
                    mSelected = firstVisiblePos;
                }
                if (mOnSelectListener != null) {
                    mOnSelectListener.onSelect(mSelected, mDatas.get(mSelected));
                }

            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            setSelectedItem();
        }
    }

    private void setSelectedItem(){
        //获取可视范围的第一个控件的位置
        int firstVisiblePos = mLayoutManager.findFirstVisibleItemPosition();
        if (firstVisiblePos == RecyclerView.NO_POSITION) {
            return;
        }
        Rect rect = new Rect();
        mLayoutManager.findViewByPosition(firstVisiblePos).getHitRect(rect);
        //被选中item是否已经滑动超出中间区域
        boolean overScroll = Math.abs(rect.top) > mItemHeight / 2 ? true : false;
        //更新可视范围内所有item的样式
        for (int i = 0; i < 1 + mOffset * 2; i++) {
            TextView item;
            if (overScroll) {
                item = (TextView) mLayoutManager.findViewByPosition(firstVisiblePos + i + 1);
            } else {
                item = (TextView) mLayoutManager.findViewByPosition(firstVisiblePos + i);
            }

            if (i == mOffset) {
                item.setTextColor(mSelectTextColor);
                item.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSelectTextSize);
            } else {
                item.setTextColor(mUnselectTextColor);
                item.setTextSize(TypedValue.COMPLEX_UNIT_PX, mUnselectTextSize);
            }
        }
    }

    private class DividerItemDecoration extends ItemDecoration {
        @Override
        public void onDrawOver(Canvas c, RecyclerView parent, State state) {
            //绘制分割线
            float startX = getMeasuredWidth() / 2 - mDividerWidth / 2;
            float topY = mItemHeight * mOffset;
            float endX = getMeasuredWidth() / 2 + mDividerWidth / 2;
            float bottomY = mItemHeight * (mOffset + 1);

            c.drawLine(startX, topY, endX, topY, mPaint);
            c.drawLine(startX, bottomY, endX, bottomY, mPaint);
        }
    }
    public interface OnSelectListener {
        void onSelect(int position, String data);
    }

}
 
 
public class CityPicker implements PopupWindow.OnDismissListener, View.OnClickListener {
    private OnCitySelectListener mOnCitySelectListener;
    private PopupWindow mPickerWindow;
    private View mParent;
    private WheelRecyclerView mProvinceWheel;
    private WheelRecyclerView mCityWheel;
    private WheelRecyclerView mCountyWheel;
    private Activity mContext;
    private List<String> provinces = new ArrayList<>();
    private List<String> citys = new ArrayList<>();
    private List<String> areas = new ArrayList<>();
    List<Province> provinceList;
    List<City> listcity;
    List<String> listarea;

    public CityPicker(Activity context, View parent) {
        mContext = context;
        mParent = parent;
        //初始化选择器
        View pickerView = LayoutInflater.from(context).inflate(R.layout.city_picker, null);
        mProvinceWheel = (WheelRecyclerView) pickerView.findViewById(R.id.wheel_province);
        mCityWheel = (WheelRecyclerView) pickerView.findViewById(R.id.wheel_city);
        mCountyWheel = (WheelRecyclerView) pickerView.findViewById(R.id.wheel_county);
        pickerView.findViewById(R.id.tv_exit).setOnClickListener(this);
        pickerView.findViewById(R.id.tv_ok).setOnClickListener(this);
        mPickerWindow = new PopupWindow(pickerView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
        mPickerWindow.setBackgroundDrawable(new ColorDrawable(Color.WHITE));
        mPickerWindow.setFocusable(true);
        mPickerWindow.setAnimationStyle(R.style.CityPickerAnim);
        mPickerWindow.setOnDismissListener(this);
        initData();
    }
    /**
     * 初始化城市数据
     */
    private void initData() {
        provinceList=new ArrayList<>();
        if (provinceList.size()>0){
            provinceList.clear();
        }
        provinceList = readFromAssets(mContext);
        citys.clear();
        List<City> list = provinceList.get(0).getList();
        citys.clear();
        for (City bean : list) {

            citys.add(bean.getName());
            mCityWheel.setData(citys);
        }
         listarea = provinceList.get(0).getList().get(0).getList();
        areas.clear();
        for (String str : listarea) {
            areas.add(str);
            mCountyWheel.setData(areas);
        }
        for (Province bean : provinceList) {
            provinces.add(bean.getName());
        }
        mProvinceWheel.setData(provinces);
        mProvinceWheel.setOnSelectListener(new WheelRecyclerView.OnSelectListener() {
            @Override
            public void onSelect(int position, String data) {
                listcity = provinceList.get(position).getList();
                if (citys.size() > 0) {
                    citys.clear();
                }
                for (City bean : listcity) {
                    citys.add(bean.getName());
                }
                mCityWheel.setData(citys);
                if (listcity == null || listcity.size() == 0) {
                    if (areas.size() > 0) {
                        areas.clear();
                    }
                    mCountyWheel.setData(areas);
                }
                if (listcity.size() > 0) {
                    listarea = listcity.get(0).getList();
                    if (areas.size() > 0) {
                        areas.clear();
                    }
                    for (String str : listarea) {
                        areas.add(str);
                    }
                    mCountyWheel.setData(areas);
                }
            }
        });
        mCityWheel.setOnSelectListener(new WheelRecyclerView.OnSelectListener() {
            @Override
            public void onSelect(int position, String data) {
                listarea = listcity.get(position).getList();
                if (areas.size() > 0) {
                    areas.clear();
                }
                for (String str : listarea) {
                    areas.add(str);
                }
                mCountyWheel.setData(areas);
            }
        });
    }


    /**
     * 弹出Window时使背景变暗
     *
     * @param alpha
     */
    private void backgroundAlpha(float alpha) {
        Window window = mContext.getWindow();
        WindowManager.LayoutParams lp = window.getAttributes();
        lp.alpha = alpha;
        window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        window.setAttributes(lp);
    }

    public CityPicker setOnCitySelectListener(OnCitySelectListener listener) {
        mOnCitySelectListener = listener;
        return this;
    }

    public void show() {
        backgroundAlpha(0.5f);
        mPickerWindow.showAtLocation(mParent, Gravity.BOTTOM, 0, 0);
    }

    @Override
    public void onDismiss() {
        backgroundAlpha(1f);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_ok:
                if (mOnCitySelectListener != null) {
                    String provinceName = provinces.get(mProvinceWheel.getSelected());
                    String cityName = "", countyName = "";
                    if (citys.size() > 0) {
                        cityName = citys.get(mCityWheel.getSelected());
                    }
                    if (areas.size() > 0) {
                        countyName = areas.get(mCountyWheel.getSelected());
                    }
                    mOnCitySelectListener.onCitySelect(provinceName, cityName, countyName);
                    mPickerWindow.dismiss();
                }
                break;
            case R.id.tv_exit:
                mPickerWindow.dismiss();
                break;
        }
    }
    public interface OnCitySelectListener {
        void onCitySelect(String province, String city, String county);
    }
 
 
 
 
 
 
public List<Province> readFromAssets(Context context) {
    List<Province> list = null;
    try {
        list = new ArrayList<>();
        InputStream inputStream = context.getAssets().open("province.json");
        String text = readTextFromSDcard(inputStream);
        inputStream.close();

        JSONArray jsonArray = new JSONArray(text);
        for (int i = 0; i < jsonArray.length(); i++) {
            Province province = new Province();
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            province.setName(jsonObject.get("name") + "");
            JSONArray jsonArray1 = jsonObject.getJSONArray("city");
            List<City> cityList = new ArrayList<>();

            for (int j = 0; j < jsonArray1.length(); j++) {
                JSONObject object = jsonArray1.getJSONObject(j);
                City city = new City();

                city.setName(object.get("name") + "");
                JSONArray jsonArray2 = object.getJSONArray("area");

                List<String> list1 = new ArrayList<>();
                for (int m = 0; m < jsonArray2.length(); m++) {
                    String strlist = jsonArray2.getString(m);
                    list1.add(strlist);
                }

                city.setList(list1);
                cityList.add(city);
            }
            province.setList(cityList);
            list.add(province);

        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return list;
}

private String readTextFromSDcard(InputStream is) {
    StringBuffer buffer = null;
    try {
        InputStreamReader reader = new InputStreamReader(is, "utf-8");
        BufferedReader bufferedReader = new BufferedReader(reader);
        buffer = new StringBuffer("");
        String str;
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
            buffer.append("\n");
        }
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return buffer.toString();
}

布局文件
<?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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_exit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="start"
            android:background="?selectableItemBackgroundBorderless"
            android:gravity="center"
            android:padding="14dp"
            android:text="取消"
            android:textColor="@color/color136"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:background="?selectableItemBackgroundBorderless"
            android:gravity="center"
            android:padding="14dp"
            android:text="城市选择"
            android:textColor="@color/color0"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/tv_ok"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:background="?selectableItemBackgroundBorderless"
            android:gravity="center"
            android:padding="14dp"
            android:text="确定"
            android:textColor="@color/color136"
            android:textSize="16sp" />
    </FrameLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"

        android:orientation="horizontal">

        <com.wf.kdb.customview.citypickerview.WheelRecyclerView
            android:id="@+id/wheel_province"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:dividerWidth="80dp" />

        <com.wf.kdb.customview.citypickerview.WheelRecyclerView
            android:id="@+id/wheel_city"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:dividerWidth="80dp" />

        <com.wf.kdb.customview.citypickerview.WheelRecyclerView
            android:id="@+id/wheel_county"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:dividerWidth="80dp" />
    </LinearLayout>
</LinearLayout>


猜你喜欢

转载自blog.csdn.net/qq_22060403/article/details/79710125