安卓城市选择,列表显示,拼音排序,滑动选择。

       最近开发项目有一个需要,选择城市,有三级滚筒式的,有些丑,所以参考了他人的联系人列表选择做了一个。先上图看下效果:

https://img-blog.csdn.net/20170112141746730?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbjEwMDAx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center


        具体效果,为左边显示城市列表,在每个拼音的开头显示大写字母,右边的控件点击滑动,会在中间显示选中的字母,并有小框框显示,列表滑动到相应的字母处。

        必须引入汉字转拼音开源库:https://github.com/stuxuhai/jpinyin

具体代码如下:

右侧字母表自定义控件:

public class SideCityBar extends View {
    private String[] letterStrings = {"#", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "S", "Y", "Z"};
    private Paint paint;
    private Paint mPaint;
    private Context mContext;
    private int heght;
    private int postion;
    private boolean isShow = false;
    private Rect rect = new Rect();

    public SideCityBar(Context context) {
        super(context);
        init(context);
    }

    public SideCityBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public SideCityBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mPaint = new Paint();
        mPaint.setColor(Color.WHITE);
        mPaint.setTextSize(30);
        mPaint.setAntiAlias(true);

        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        heght = getHeight() / letterStrings.length;
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        setBackgroundColor(Color.BLACK);


        for (int i = 0; i < letterStrings.length; i++) {
            String s1 = letterStrings[i];
            mPaint.getTextBounds(s1, 0, s1.length(), rect);
            int h1 = rect.height();
            int w1 = rect.width();
            //  mPaint.measureText(s1)只需要文字宽度可用此方法。
            int h2 = heght / 2 + h1 / 2 + heght * i;
            int w2 = getWidth() / 2 - w1 / 2;
            canvas.drawText(s1, w2, h2, mPaint);
            if (isShow && (i == postion)) {
                canvas.drawRect((getWidth() - heght) / 2, (0 + i * heght), (getWidth() + heght) / 2, (heght + i * heght), paint);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float y1 = event.getY();
        if (event.getAction() == MotionEvent.ACTION_UP) {
            isShow = false;
            mTextView.setVisibility(GONE);
            mOnchangeString.setTextShow(false);
            invalidate();
            return true;
        } else {
            isShow = true;
            //计算框框的位置
            postion = (int) (y1 / heght);
            if (postion < letterStrings.length) {
                mTextView.setVisibility(VISIBLE);
                mTextView.setText(letterStrings[postion]);
                mOnchangeString.getChangeString(letterStrings[postion]);
                mOnchangeString.setTextShow(true);
                invalidate();
            }

            return true;
        }
    }

    TextView mTextView;

    public void setTextView(TextView textView) {
        mTextView = textView;
    }

    public void setOnChangeLis(OnchangeString onChangeLis) {
        mOnchangeString = onChangeLis;
    }

    OnchangeString mOnchangeString;

    public interface OnchangeString {
        void getChangeString(String s);

        void setTextShow(boolean b);
    }
}

数据封装类:
public class CityModel {
    private String name;
    private String fistletter;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getFistletter() {
        return fistletter;
    }

    public void setFistletter(String fistletter) {
        this.fistletter = fistletter;
    }
}

接着就是主布局和列表布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="match_parent"
   >


    <ListView
        android:id="@+id/l1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:id="@+id/t1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        android:background="#3CAC48"
        android:gravity="center"
        android:textColor="#ffffff"
        android:textSize="50dp"
        android:visibility="gone" />

    <allother.two.sidecity.SideCityBar
        android:id="@+id/s1"
        android:layout_width="40dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true" />
</RelativeLayout>
<?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="match_parent"
    android:orientation="vertical">


    <TextView
        android:id="@+id/t1"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:text="A" />

    <TextView
        android:id="@+id/t2"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:text="A" />

</LinearLayout>
最后是我们的主要Activity:

public class SideCityActivity extends AppCompatActivity {
    private String TAG = "SideCityActivity:";
    private ListView listView;
    private TextView txtShowCurrentLetter;
    private SideCityBar sideBar;
    private List<CityModel> list = new ArrayList();
    private SideBarCityAdapter sideBarCityAdapter;
    private Map<String, Integer> map = new HashMap<>();
    private String[] nameStrings = {"$XXOO", "上海", "北京", "杭州", "广州", "南京", "苏州", "深圳", "成都", "重庆", "天津", "宁波", "扬州", "无锡", "福州",
            "厦门", "武汉", "西安", "沈阳", "大连", "青岛", "济南", "海口", "石家庄", "唐山", "秦皇岛", "邯郸", "邢台", "保定", "张家口", "承德", "沧州", "廊坊",
            "衡水", "太原", "大同", "阳泉", "长治", "晋城", "朔州", "晋中", "运城", "忻州", "临汾", "吕梁", "呼和浩特", "包头", "乌海", "赤峰", "通辽", "鄂尔多斯",
            "呼伦贝尔", "兴安盟", "锡林郭勒", "乌兰察布", "巴彦淖尔", "阿拉善", "鞍山", "抚顺", "本溪", "丹东", "锦州", "营口", "阜新", "辽阳", "盘锦", "铁岭", "朝阳",
            "葫芦岛", "长春", "吉林", "四平", "辽源", "通化", "白山", "松原", "白城", "延边", "哈尔滨", "齐齐哈尔", "鸡西", "鹤岗", "双鸭山", "大庆", "伊春", "佳木斯", "七台河",
            "牡丹江", "黑河", "绥化", "大兴安岭", "徐州", "常州", "南通", "连云港", "淮安", "盐城", "镇江", "泰州", "宿迁", "温州", "嘉兴", "湖州", "绍兴", "金华", "衢州", "舟山", "台州",
            "丽水", "合肥", "芜湖", "蚌埠", "淮南", "马鞍山", "淮北", "铜陵", "安庆", "黄山", "滁州", "阜阳", "宿州", "六安", "亳州", "池州", "宣城", "莆田", "三明", "泉州", "漳州", "南平", "龙岩",
            "宁德", "南昌", "景德镇", "萍乡", "九江", "新余", "鹰潭", "赣州", "吉安", "宜春", "抚州", "上饶", "淄博", "枣庄", "东营", "烟台", "潍坊", "济宁", "泰安", "威海", "日照", "莱芜", "临沂", "德州",
            "聊城", "滨州", "菏泽", "郑州", "开封", "洛阳", "平顶山", "安阳", "鹤壁", "新乡", "焦作", "濮阳", "许昌", "漯河", "三门峡", "南阳", "商丘", "信阳", "周口", "驻马店", "黄石", "十堰", "宜昌", "襄阳", "鄂州",
            "荆门", "孝感", "荆州", "黄冈", "咸宁", "随州", "恩施州", "仙桃", "潜江", "天门", "株洲", "湘潭", "衡阳", "邵阳", "岳阳", "常德", "张家界", "益阳", "郴州", "永州", "怀化", "娄底", "湘西", "韶关", "珠海", "汕头",
            "佛山", "江门", "湛江", "茂名", "肇庆", "惠州", "梅州", "汕尾", "河源", "阳江", "清远", "东莞", "中山", "潮州", "揭阳", "云浮", "南宁", "柳州", "桂林", "梧州", "北海", "防城港", "钦州", "贵港", "玉林", "百色", "贺州",
            "河池", "自贡", "攀枝花", "泸州", "德阳", "绵阳", "广元", "遂宁", "内江", "乐山", "南充", "眉山", "宜宾", "广安", "达州", "雅安", "巴中", "资阳", "阿坝", "甘孜州", "凉山", "贵阳", "六盘水", "遵义", "安顺", "铜仁地区",
            "黔西南", "毕节地区", "黔东南", "黔南", "昆明", "曲靖", "玉溪", "保山", "昭通", "楚雄州", "红河", "文山州", "普洱", "西双版纳", "大理州", "德宏", "丽江", "怒江", "迪庆", "临沧", "拉萨", "昌都地区", "山南",
            "日喀则地区", "那曲", "阿里", "林芝地区", "铜川", "宝鸡", "咸阳", "渭南", "延安", "汉中", "榆林", "安康", "商洛", "兰州", "嘉峪关", "金昌", "白银", "天水", "武威", "张掖", "平凉", "酒泉", "庆阳", "定西",
            "陇南", "临夏州", "甘南", "西宁", "海东", "海北", "黄南", "果洛", "玉树", "海西", "银川", "石嘴山", "吴忠", "固原", "乌鲁木齐", "克拉玛依", "吐鲁番地区", "哈密地区", "昌吉州", "博尔塔拉", "巴音郭楞",
            "阿克苏地区", "克孜勒苏", "喀什地区", "和田地区", "伊犁", "塔城地区", "阿勒泰地区", "石河子", "香港", "澳门", "长沙", "三亚", "中卫", "儋州", "保亭", "昌江", "澄迈县", "崇左", "定安县", "东方", "济源",
            "来宾", "乐东", "陵水", "琼海", "神农架林区", "图木舒克", "屯昌县", "万宁", "文昌", "海南州"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_two_sidecity);
        txtShowCurrentLetter = (TextView) findViewById(R.id.t1);
        sideBar = (SideCityBar) findViewById(R.id.s1);
        listView = (ListView) findViewById(R.id.l1);
        sideBar.setTextView(txtShowCurrentLetter);
        getAllData();
        sideBarCityAdapter = new SideBarCityAdapter();
        listView.setAdapter(sideBarCityAdapter);

        sideBar.setOnChangeLis(new SideCityBar.OnchangeString() {
            @Override
            public void getChangeString(String s) {
                int a1 = getCurrentPosition(s);
                if (a1 != -1) {
                    listView.setSelection(a1);
                } else {

                }
            }

            @Override
            public void setTextShow(boolean b) {

            }
        });
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String city = list.get(position).getName();
            }
        });
    }

    /**
     * list获取所有数据
     */
    private void getAllData() {
        list = new ArrayList();
        for (int i = 0; i < nameStrings.length; i++) {
            CityModel cityModel = new CityModel();
            cityModel.setName(nameStrings[i]);
            //将汉字转换为拼音
            String pin = PinyinHelper.getShortPinyin(nameStrings[i]);
            //将拼音字符串转换为大写拼音
            String pinD = String.valueOf(pin.charAt(0)).toUpperCase();
            //获取大写拼音字符串的第一个字符
            char c1 = pinD.charAt(0);
            if (c1 < 'A' || c1 > 'Z') {
                cityModel.setFistletter("#");
            } else {
                cityModel.setFistletter(String.valueOf(c1));
            }
            list.add(cityModel);
        }
        //将联系人列表的标题字母排序
        Collections.sort(list, new Comparator<CityModel>() {
            @Override
            public int compare(CityModel o1, CityModel o2) {
                return o1.getFistletter().compareTo(o2.getFistletter());
            }
        });
        //记录字母所在位置
        String s1 = list.get(0).getFistletter();
        map.put(s1, 0);
        for (int i = 0; i < list.size(); i++) {
            String s2 = list.get(i).getFistletter();
            if (!s1.equals(s2)) {
                s1 = s2;
                map.put(s2, i);
            }
        }
    }


    private int getCurrentPosition(String s) {
        if (map.get(s) != null) {
            return map.get(s);
        } else {
            return -1;
        }
    }


    public class SideBarCityAdapter extends BaseAdapter {


        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Object getItem(int position) {
            return list.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                viewHolder = new ViewHolder();
                convertView = LayoutInflater.from(SideCityActivity.this).inflate(R.layout.act_two_sidecity_item, null);
                viewHolder.txtFirstLetter = (TextView) convertView.findViewById(R.id.t1);
                viewHolder.txtName = (TextView) convertView.findViewById(R.id.t2);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            viewHolder.txtName.setText(list.get(position).getName());
            String s1 = list.get(position).getFistletter();
            if (map.get(s1) != null && map.get(s1).equals(position)) {
                viewHolder.txtFirstLetter.setText(s1);
                viewHolder.txtFirstLetter.setVisibility(View.VISIBLE);
            } else {
                viewHolder.txtFirstLetter.setVisibility(View.GONE);
            }

            return convertView;
        }

        public class ViewHolder {
            TextView txtFirstLetter, txtName;
        }


    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值