当前位置: 代码迷 >> Android >> android listview兑现快速查询A—Z (模拟一些天气搜狐,网易等天气预报)
  详细解决方案

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

热度:36   发布时间:2016-05-01 17:39:19.0
android listview实现快速查询A—Z (模拟一些天气搜狐,网易等天气预报)

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

                        

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

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

       代码片段:

public class MySideBar extends View {	private TextView textView;// 显示框	private boolean showBkg = false;	// 触摸事件	OnTouchingLetterChangedListener onTouchingLetterChangedListener;	// 26个字母	public static String[] b = { "#", "A", "B", "C", "D", "E", "F", "G", "H",			"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",			"V", "W", "X", "Y", "Z" };	int choose = -1;// 选中	Paint paint = new Paint();	// 自定义view 最好注明这三个构造函数	public MySideBar(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);	}	public MySideBar(Context context, AttributeSet attrs) {		super(context, attrs);	}	public MySideBar(Context context) {		super(context);	}	/**	 * 重写这个方法	 */	protected void onDraw(Canvas canvas) {		super.onDraw(canvas);		// 获取焦点改变背景颜色.		if (showBkg) {			canvas.drawColor(Color.parseColor("#40000000"));		}		int height = getHeight()-30;// 获取对应高度		int width = getWidth(); // 获取对应宽度		int singleHeight = height / b.length;// 获取每一个字母的高度		for (int i = 0; i < b.length; i++) {			paint.setColor(Color.BLACK);			// paint.setColor(Color.WHITE);			paint.setTypeface(Typeface.DEFAULT_BOLD);			paint.setAntiAlias(true);			paint.setTextSize(20);			// 选中的状态			if (i == choose) {				paint.setColor(Color.parseColor("#3399ff"));				paint.setFakeBoldText(true);			}			// x坐标等于中间-字符串宽度的一半.			float xPos = width / 2 - paint.measureText(b[i]) / 2;			float yPos = singleHeight * i + singleHeight;			canvas.drawText(b[i], xPos, yPos, paint);			paint.reset();// 重置画笔		}	}	@Override	public boolean dispatchTouchEvent(MotionEvent event) {		final int action = event.getAction();		final float y = event.getY();// 点击y坐标		final int oldChoose = choose;		final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;		final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.		switch (action) {		case MotionEvent.ACTION_DOWN:			showBkg = true;			if (oldChoose != c && listener != null) {				if (c > 0 && c < b.length) {					listener.onTouchingLetterChanged(b[c]);// 执行onTouchingLetterChanged事件.					choose = c;// 选项					invalidate();// 刷新				}			}			break;		case MotionEvent.ACTION_MOVE:			if (oldChoose != c && listener != null) {				if (c > 0 && c < b.length) {					listener.onTouchingLetterChanged(b[c]);					choose = c;					invalidate();				}			}			break;		case MotionEvent.ACTION_UP:			showBkg = false;			choose = -1;//			invalidate();			textView.setVisibility(View.GONE);			break;		}		return true;	}	public void setTextView(TextView textView) {		this.textView = textView;	}	/**	 * 向外公开的方法	 * 	 * @param onTouchingLetterChangedListener	 */	public void setOnTouchingLetterChangedListener(			OnTouchingLetterChangedListener onTouchingLetterChangedListener) {		this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;	}	/**	 * 接口	 * 	 * @author coder	 * 	 */	public interface OnTouchingLetterChangedListener {		public void onTouchingLetterChanged(String s);	}}


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

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

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

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

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

     实现ListView的适配器.

/***	 * 自定义Adapter	 * 	 * @author zhangjia	 * 	 */	class MyAdapter extends BaseAdapter {		private Context context;		public MyAdapter(Context context) {			super();			this.context = context;		}		@Override		public int getCount() {			return MySideBar.b.length;			// return MySideBar.b.length;		}		@Override		public Object getItem(int position) {			// TODO Auto-generated method stub			return null;		}		@Override		public long getItemId(int position) {			// TODO Auto-generated method stub			return 0;		}		@Override		public View getView(int position, View convertView, ViewGroup parent) {			TextView textView;			if (convertView == null) {				holder = new ViewHolder();				convertView = (LinearLayout) LayoutInflater.from(context)						.inflate(R.layout.item, null);				holder.textView = (TextView) convertView						.findViewById(R.id.tv_item);				holder.listView = (ListView) convertView						.findViewById(R.id.lv_item);				convertView.setTag(holder);			} else {				holder = (ViewHolder) convertView.getTag();			}			final String textValue = mySideBar.b[position];// A...B...C			// 显示该控件			holder.textView.setVisibility(View.VISIBLE);			holder.listView.setVisibility(View.VISIBLE);			if (position == 0) {				holder.textView.setText("当前城市");			} else {				holder.textView.setText(textValue);			}			child = getListView(textValue);			holder.listView.setAdapter(child);			// 设置样式(宽度)			setListViewHeightBasedOnChildren(holder.listView);			if (child.getCount() == 0) {				// 没有项的让该控件消失				holder.textView.setVisibility(View.GONE);				holder.listView.setVisibility(View.GONE);			}			holder.listView.setOnItemClickListener(new OnItemClickListener() {				@Override				public void onItemClick(AdapterView<?> parent, View view,						int position, long id) {					// parent.getItemAtPosition(position).toString();根据item提示,这样万无一失					Toast.makeText(MainActivity.this,							parent.getItemAtPosition(position).toString(), 1000)							.show();				}			});			return convertView;		}	}
在这里我们会遇到一个问题就是listivew中嵌套listview,显示我们需要对listview进行动态设置ilistview的高度.

/***	 * 动态设置listview的高度	 * 	 * @param listView	 */	public void setListViewHeightBasedOnChildren(ListView listView) {		ListAdapter listAdapter = listView.getAdapter();		if (listAdapter == null) {			return;		}		int totalHeight = 0;		for (int i = 0; i < listAdapter.getCount(); i++) {			View listItem = listAdapter.getView(i, null, listView);			listItem.measure(0, 0);			totalHeight += listItem.getMeasuredHeight();		}		ViewGroup.LayoutParams params = listView.getLayoutParams();		params.height = totalHeight				+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));		// params.height += 5;// if without this statement,the listview will be		// a		// little short		// listView.getDividerHeight()获取子项间分隔符占用的高度		// params.height最后得到整个ListView完整显示需要的高度		listView.setLayoutParams(params);	}
这样外面的listview就会根据子listview的高度定制自己的高度.

 调用代码(实现OnTouchingLetterChangedListener接口)

	@Override	public void onTouchingLetterChanged(String s) {		overlay.setText(s);		overlay.setBackgroundColor(Color.GRAY);		overlay.setVisibility(View.VISIBLE);		int position = arrayList.indexOf(s);		lvMain.setSelection(position);	}
@Override	public void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		InitView();//初始view		et_main.addTextChangedListener(textWatcher);		cityManager.InitData();// 创建数据库		adapter = new MyAdapter(this);		lvMain.setAdapter(adapter);		arrayList = new ArrayList<String>();		for (int i = 0; i < MySideBar.b.length; i++) {			arrayList.add(MySideBar.b[i]);		}	}
以上就是主要实现代码.


   项目展示:

                     

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

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

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

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


1楼keyboard_workers4小时前
效果不错,支持.
  相关解决方案