android listview实现快速查询A—Z (模拟一些天气搜狐,网易等天气预报)

首先还是老样子,我们先来看一些应用视图:

                        

       这个应用很酷吧,可以很方面我们找到所要的城市及实现天气查询订阅等.但是我要在这里提一下搜狐的意见了,这个错误很明显,城市J开头的你却用I来提示,而J你pass掉了,看来还是网易比较好.不东扯西扯了.

       首先我们要实现右边提示的view,这里面我们要自定义,这里是参考别人的. 

       代码片段:

[java]  view plain copy
  1. public class MySideBar extends View {  
  2.   
  3.     private TextView textView;// 显示框  
  4.   
  5.     private boolean showBkg = false;  
  6.     // 触摸事件  
  7.     OnTouchingLetterChangedListener onTouchingLetterChangedListener;  
  8.     // 26个字母  
  9.     public static String[] b = { "#""A""B""C""D""E""F""G""H",  
  10.             "I""J""K""L""M""N""O""P""Q""R""S""T""U",  
  11.             "V""W""X""Y""Z" };  
  12.     int choose = -1;// 选中  
  13.     Paint paint = new Paint();  
  14.   
  15.     // 自定义view 最好注明这三个构造函数  
  16.     public MySideBar(Context context, AttributeSet attrs, int defStyle) {  
  17.         super(context, attrs, defStyle);  
  18.     }  
  19.   
  20.     public MySideBar(Context context, AttributeSet attrs) {  
  21.         super(context, attrs);  
  22.     }  
  23.   
  24.     public MySideBar(Context context) {  
  25.         super(context);  
  26.     }  
  27.   
  28.     /** 
  29.      * 重写这个方法 
  30.      */  
  31.     protected void onDraw(Canvas canvas) {  
  32.         super.onDraw(canvas);  
  33.         // 获取焦点改变背景颜色.  
  34.         if (showBkg) {  
  35.             canvas.drawColor(Color.parseColor("#40000000"));  
  36.         }  
  37.         int height = getHeight()-30;// 获取对应高度  
  38.         int width = getWidth(); // 获取对应宽度  
  39.         int singleHeight = height / b.length;// 获取每一个字母的高度  
  40.   
  41.         for (int i = 0; i < b.length; i++) {  
  42.             paint.setColor(Color.BLACK);  
  43.             // paint.setColor(Color.WHITE);  
  44.             paint.setTypeface(Typeface.DEFAULT_BOLD);  
  45.             paint.setAntiAlias(true);  
  46.             paint.setTextSize(20);  
  47.             // 选中的状态  
  48.             if (i == choose) {  
  49.                 paint.setColor(Color.parseColor("#3399ff"));  
  50.                 paint.setFakeBoldText(true);  
  51.             }  
  52.             // x坐标等于中间-字符串宽度的一半.  
  53.             float xPos = width / 2 - paint.measureText(b[i]) / 2;  
  54.             float yPos = singleHeight * i + singleHeight;  
  55.             canvas.drawText(b[i], xPos, yPos, paint);  
  56.             paint.reset();// 重置画笔  
  57.         }  
  58.   
  59.     }  
  60.   
  61.     @Override  
  62.     public boolean dispatchTouchEvent(MotionEvent event) {  
  63.         final int action = event.getAction();  
  64.         final float y = event.getY();// 点击y坐标  
  65.         final int oldChoose = choose;  
  66.         final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;  
  67.         final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.  
  68.   
  69.         switch (action) {  
  70.         case MotionEvent.ACTION_DOWN:  
  71.             showBkg = true;  
  72.             if (oldChoose != c && listener != null) {  
  73.                 if (c > 0 && c < b.length) {  
  74.   
  75.                     listener.onTouchingLetterChanged(b[c]);// 执行onTouchingLetterChanged事件.  
  76.                     choose = c;// 选项  
  77.                     invalidate();// 刷新  
  78.                 }  
  79.             }  
  80.   
  81.             break;  
  82.         case MotionEvent.ACTION_MOVE:  
  83.             if (oldChoose != c && listener != null) {  
  84.                 if (c > 0 && c < b.length) {  
  85.                     listener.onTouchingLetterChanged(b[c]);  
  86.                     choose = c;  
  87.                     invalidate();  
  88.                 }  
  89.             }  
  90.             break;  
  91.         case MotionEvent.ACTION_UP:  
  92.             showBkg = false;  
  93.             choose = -1;//  
  94.             invalidate();  
  95.             textView.setVisibility(View.GONE);  
  96.             break;  
  97.         }  
  98.         return true;  
  99.     }  
  100.   
  101.     public void setTextView(TextView textView) {  
  102.         this.textView = textView;  
  103.     }  
  104.   
  105.     /** 
  106.      * 向外公开的方法 
  107.      *  
  108.      * @param onTouchingLetterChangedListener 
  109.      */  
  110.     public void setOnTouchingLetterChangedListener(  
  111.             OnTouchingLetterChangedListener onTouchingLetterChangedListener) {  
  112.         this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;  
  113.     }  
  114.   
  115.     /** 
  116.      * 接口 
  117.      *  
  118.      * @author coder 
  119.      *  
  120.      */  
  121.     public interface OnTouchingLetterChangedListener {  
  122.         public void onTouchingLetterChanged(String s);  
  123.     }  
  124.   
  125. }  


 注释很详细,我想大家一看就OK了.

 下面我们要实现主页面的内容.

      看到这个样式,我郁闷好久,用什么来实现呢,之前做过这个.android 解决ScrollView与ListView的冲突(TableLayout+ScrollView) 。所以就想到用Listview +TableView,结果遇到了一大堆问题,后来反过来用也是,总结一句话控件没学好,如果学的深的话,这些都可以解决的,有时间得用这几种方式做做.也许最简单的实现是“ListView嵌套ListView”.

      这里面肯定会出现问题,就是item显示的问题.         

    下面是实现代码:(声明,有点乱,不过都不难,我想你OK没问题)

     实现ListView的适配器.

[java]  view plain copy
  1. /*** 
  2.      * 自定义Adapter 
  3.      *  
  4.      * @author zhangjia 
  5.      *  
  6.      */  
  7.     class MyAdapter extends BaseAdapter {  
  8.         private Context context;  
  9.   
  10.         public MyAdapter(Context context) {  
  11.             super();  
  12.             this.context = context;  
  13.         }  
  14.   
  15.         @Override  
  16.         public int getCount() {  
  17.             return MySideBar.b.length;  
  18.             // return MySideBar.b.length;  
  19.         }  
  20.   
  21.         @Override  
  22.         public Object getItem(int position) {  
  23.             // TODO Auto-generated method stub  
  24.             return null;  
  25.         }  
  26.   
  27.         @Override  
  28.         public long getItemId(int position) {  
  29.             // TODO Auto-generated method stub  
  30.             return 0;  
  31.         }  
  32.   
  33.         @Override  
  34.         public View getView(int position, View convertView, ViewGroup parent) {  
  35.             TextView textView;  
  36.             if (convertView == null) {  
  37.                 holder = new ViewHolder();  
  38.                 convertView = (LinearLayout) LayoutInflater.from(context)  
  39.                         .inflate(R.layout.item, null);  
  40.                 holder.textView = (TextView) convertView  
  41.                         .findViewById(R.id.tv_item);  
  42.                 holder.listView = (ListView) convertView  
  43.                         .findViewById(R.id.lv_item);  
  44.                 convertView.setTag(holder);  
  45.             } else {  
  46.                 holder = (ViewHolder) convertView.getTag();  
  47.             }  
  48.             final String textValue = mySideBar.b[position];// A...B...C  
  49.             // 显示该控件  
  50.             holder.textView.setVisibility(View.VISIBLE);  
  51.             holder.listView.setVisibility(View.VISIBLE);  
  52.             if (position == 0) {  
  53.                 holder.textView.setText("当前城市");  
  54.             } else {  
  55.                 holder.textView.setText(textValue);  
  56.             }  
  57.             child = getListView(textValue);  
  58.             holder.listView.setAdapter(child);  
  59.             // 设置样式(宽度)  
  60.             setListViewHeightBasedOnChildren(holder.listView);  
  61.   
  62.             if (child.getCount() == 0) {  
  63.                 // 没有项的让该控件消失  
  64.                 holder.textView.setVisibility(View.GONE);  
  65.                 holder.listView.setVisibility(View.GONE);  
  66.             }  
  67.   
  68.             holder.listView.setOnItemClickListener(new OnItemClickListener() {  
  69.                 @Override  
  70.                 public void onItemClick(AdapterView<?> parent, View view,  
  71.                         int position, long id) {  
  72.                     // parent.getItemAtPosition(position).toString();根据item提示,这样万无一失  
  73.                     Toast.makeText(MainActivity.this,  
  74.                             parent.getItemAtPosition(position).toString(), 1000)  
  75.                             .show();  
  76.                 }  
  77.             });  
  78.             return convertView;  
  79.         }  
  80.     }  
在这里我们会遇到一个问题就是listivew中嵌套listview,显示我们需要对listview进行动态设置ilistview的高度.
[java]  view plain copy
  1. /*** 
  2.      * 动态设置listview的高度 
  3.      *  
  4.      * @param listView 
  5.      */  
  6.     public void setListViewHeightBasedOnChildren(ListView listView) {  
  7.         ListAdapter listAdapter = listView.getAdapter();  
  8.         if (listAdapter == null) {  
  9.             return;  
  10.         }  
  11.         int totalHeight = 0;  
  12.         for (int i = 0; i < listAdapter.getCount(); i++) {  
  13.             View listItem = listAdapter.getView(i, null, listView);  
  14.             listItem.measure(00);  
  15.             totalHeight += listItem.getMeasuredHeight();  
  16.         }  
  17.         ViewGroup.LayoutParams params = listView.getLayoutParams();  
  18.         params.height = totalHeight  
  19.                 + (listView.getDividerHeight() * (listAdapter.getCount() - 1));  
  20.         // params.height += 5;// if without this statement,the listview will be  
  21.         // a  
  22.         // little short  
  23.         // listView.getDividerHeight()获取子项间分隔符占用的高度  
  24.         // params.height最后得到整个ListView完整显示需要的高度  
  25.         listView.setLayoutParams(params);  
  26.     }  
这样外面的listview就会根据子listview的高度定制自己的高度.

 调用代码(实现OnTouchingLetterChangedListener接口)

[java]  view plain copy
  1. @Override  
  2. public void onTouchingLetterChanged(String s) {  
  3.     overlay.setText(s);  
  4.     overlay.setBackgroundColor(Color.GRAY);  
  5.     overlay.setVisibility(View.VISIBLE);  
  6.     int position = arrayList.indexOf(s);  
  7.     lvMain.setSelection(position);  
  8. }  
[java]  view plain copy
  1. @Override  
  2.     public void onCreate(Bundle savedInstanceState) {  
  3.         super.onCreate(savedInstanceState);  
  4.         InitView();//初始view  
  5.   
  6.         et_main.addTextChangedListener(textWatcher);  
  7.   
  8.         cityManager.InitData();// 创建数据库  
  9.         adapter = new MyAdapter(this);  
  10.         lvMain.setAdapter(adapter);  
  11.   
  12.         arrayList = new ArrayList<String>();  
  13.         for (int i = 0; i < MySideBar.b.length; i++) {  
  14.             arrayList.add(MySideBar.b[i]);  
  15.         }  
  16.     }  
以上就是主要实现代码.


   项目展示:

                     

       看起来还凑合吧,最近想实现个完整的天气项目,就先搭一下架子了.哈哈.

      代码都在上面,我就不多解释了,还有一点我需要说明一下,里面的数据我们可以通过天气预报接口进行解析获取相应的城市.

解析就是请求,解析字符串,就不多说了,但是我还要明确一点就是对字母的查询,我们要获取城市的pinyin.这个是比较头疼的,虽说已经有pingyin4j.jar了,但是比较窝囊的是,多音字没有解决,为了解决这个,我走了好多弯路,用到了翻译接口,请求webservice,因为中国地名就是拼音嘛,虽知道我自错聪明,好不容易搭好了架子,虽知道解析有的偏僻地方都没有英文,我郁闷个头啊.最后解决了80%,至于方法,我不说你也知道.

     这里我把city.db上传一下,如果需要点击      链接下载


/*********************************************************************************************************************************************/

最近参考别的的实现,觉得我上面这种做法很复杂,完全没有必要用listview 嵌套listview,其实我们完全用listview就可以实现,只是对getView返回view的时候坐下判断就可以了,下面我简单介绍下,不管有没有用,总之对我很有用啊,哈哈.因为我上面那种实现起来麻烦.

首先我们先制造数据:

[java]  view plain copy
  1. public void setData() {  
  2.         list.add("A");  
  3.         listTag.add("A");  
  4.         for (int i = 0; i < 5; i++) {  
  5.             list.add("ANDROID" + i);  
  6.         }  
  7.         list.add("B");  
  8.         listTag.add("B");  
  9.         for (int i = 0; i < 5; i++) {  
  10.             list.add("IPHONE" + i);  
  11.         }  
  12.         list.add("C");  
  13.         listTag.add("C");  
  14.         for (int i = 0; i < 5; i++) {  
  15.             list.add("WINDOW" + i);  
  16.         }  
这样做的目的是让我们listview显示的时候可以指定某一个item进行自我操作.
[java]  view plain copy
  1. @Override  
  2.     public View getView(int position, View convertView, ViewGroup parent) {  
  3.         View view = convertView;  
  4.         if (listTag.contains(getItem(position))) {  
  5.             view = LayoutInflater.from(getContext()).inflate(  
  6.                     R.layout.group_list_item_tag, null);  
  7.         } else {  
  8.             view = LayoutInflater.from(getContext()).inflate(  
  9.                     R.layout.group_list_item, null);  
  10.         }  
  11.         TextView textView = (TextView) view  
  12.                 .findViewById(R.id.group_list_item_text);  
  13.         textView.setText(getItem(position));  
  14.         return view;  
  15.     }  
也很好理解,因为我们在setData的时候已经把数据标记好了,所以可以在指定的一行进行显示相应的样式.

结果样式:

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值