首先还是老样子,我们先来看一些应用视图:
这个应用很酷吧,可以很方面我们找到所要的城市及实现天气查询订阅等.但是我要在这里提一下搜狐的意见了,这个错误很明显,城市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;
- }
- }
- /***
- * 动态设置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);
- }
调用代码(实现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上传一下,如果需要点击 链接下载
/*********************************************************************************************************************************************/
最近参考别的的实现,觉得我上面这种做法很复杂,完全没有必要用listview 嵌套listview,其实我们完全用listview就可以实现,只是对getView返回view的时候坐下判断就可以了,下面我简单介绍下,不管有没有用,总之对我很有用啊,哈哈.因为我上面那种实现起来麻烦.
首先我们先制造数据:
- public void setData() {
- list.add("A");
- listTag.add("A");
- for (int i = 0; i < 5; i++) {
- list.add("ANDROID" + i);
- }
- list.add("B");
- listTag.add("B");
- for (int i = 0; i < 5; i++) {
- list.add("IPHONE" + i);
- }
- list.add("C");
- listTag.add("C");
- for (int i = 0; i < 5; i++) {
- list.add("WINDOW" + i);
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View view = convertView;
- if (listTag.contains(getItem(position))) {
- view = LayoutInflater.from(getContext()).inflate(
- R.layout.group_list_item_tag, null);
- } else {
- view = LayoutInflater.from(getContext()).inflate(
- R.layout.group_list_item, null);
- }
- TextView textView = (TextView) view
- .findViewById(R.id.group_list_item_text);
- textView.setText(getItem(position));
- return view;
- }
结果样式: