Android开发实例-健康食谱应用(一)

来源:互联网 发布:车身结构优化 编辑:程序博客网 时间:2024/06/11 16:58
转载自:http://blog.csdn.net/einarzhang/article/details/44774635

目录(?)[+]

本系列文章主要介绍如何利用Android开发一个简单的健康食谱软件。用到的相关技术如下所示:

  • 提供GridView和ListView的基本使用
  • 利用universal-image-loader异步加载网络图片
  • 通过HttpClient获取网络http请求数据
  • 滑动分页加载数据
软件所用的所有数据均来源于http://doc.yi18.net/cookwendang提供的食谱接口,感谢他们!

软件文件结构如下所示:


MainActivity:主界面Acitivity
MListActivity:子分类列表Acitivity
CListActivity:食谱列表Activity
DetailActivity:食谱详情Activity

MainGridAdapter:主界面食谱分类适配器
CListAdapter:食谱列表适配器
Cook:用于保存食谱信息的pojo

HttpUtils:提供Http请求相关功能
MUtils:提供食谱相关的处理逻辑功能

 软件主界面设计开发

 主界面主要提供了健康食谱的主分类控件,用户可以选择自己感兴趣的分类进行食谱查看。为了便于用户更好的找到自己需要的食谱,我们提供一个全局搜索功能,用户可以输入关键词搜索自己想要的食谱信息,如:萝卜,将加载出所有与萝卜相关的食谱

主界面最终效果图如下所示:


主界面共分为两大块:全局搜索布局和Grid分类布局,其布局xml如下所示:
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@drawable/list_item_bg"   
  6.     tools:context=".MainActivity" >  
  7.   
  8.     <RelativeLayout  
  9.         android:id="@+id/top_layout"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="160dp"  
  12.         android:layout_alignParentTop="true"  
  13.         android:background="@drawable/main_top" >  
  14.   
  15.         <TextView  
  16.             android:layout_width="match_parent"  
  17.             android:layout_height="50dp"  
  18.             android:background="@drawable/main_title"  
  19.             android:text="@string/app_name"  
  20.             android:gravity="center"  
  21.             android:textColor="@android:color/white"  
  22.             android:textSize="18sp"  
  23.             android:layout_alignParentTop="true" >  
  24.         </TextView>  
  25.   
  26.         <EditText  
  27.             android:id="@+id/main_input"  
  28.             android:layout_width="match_parent"  
  29.             android:layout_height="40dp"  
  30.             android:layout_alignParentBottom="true"  
  31.             android:layout_margin="20dp"  
  32.             android:background="@drawable/edit_shape"  
  33.             android:hint="@string/search_tip"  
  34.             android:lines="1"  
  35.             android:paddingLeft="32dp"  
  36.             android:paddingRight="32dp"  
  37.             android:singleLine="true"  
  38.             android:textSize="16sp" >  
  39.         </EditText>  
  40.   
  41.         <ImageView  
  42.             android:id="@+id/main_clear_btn"  
  43.             android:layout_width="wrap_content"  
  44.             android:layout_height="wrap_content"  
  45.             android:layout_alignBottom="@+id/main_input"  
  46.             android:layout_alignLeft="@+id/main_input"  
  47.             android:layout_alignTop="@+id/main_input"  
  48.             android:src="@drawable/clear" />  
  49.   
  50.         <ImageView  
  51.             android:id="@+id/main_search_btn"  
  52.             android:layout_width="wrap_content"  
  53.             android:layout_height="wrap_content"  
  54.             android:layout_alignBottom="@+id/main_input"  
  55.             android:layout_alignRight="@+id/main_input"  
  56.             android:layout_alignTop="@+id/main_input"  
  57.             android:src="@drawable/search" >  
  58.         </ImageView>  
  59.     </RelativeLayout>  
  60.   
  61.     <GridView  
  62.         android:id="@+id/main_grid"  
  63.         android:layout_width="match_parent"  
  64.         android:layout_height="match_parent"  
  65.         android:layout_below="@id/top_layout"  
  66.         android:layout_marginTop="20dp"  
  67.         android:gravity="center_horizontal"  
  68.         android:numColumns="3"  
  69.         android:scrollbars="none"  
  70.         android:verticalSpacing="20dp" >  
  71.     </GridView>  
  72.   
  73. </RelativeLayout>  

通过 http://api.yi18.net/cook/cookclass接口可以获取到所有的主分类信息。我们通过定制自有的MainGridAdapter实现GridView的渲染,源码如下所示:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.util.List;  
  2.   
  3. import android.content.Context;  
  4. import android.content.Intent;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.view.View.OnClickListener;  
  8. import android.view.ViewGroup;  
  9. import android.widget.BaseAdapter;  
  10. import android.widget.ImageView;  
  11. import android.widget.TextView;  
  12.   
  13. public class MainGridAdapter extends BaseAdapter {  
  14.       
  15.     private List<Item> items;  
  16.     private Context ctx;  
  17.       
  18.     public MainGridAdapter(List<Item> items, Context ctx) {  
  19.         this.items = items;  
  20.         this.ctx = ctx;  
  21.     }  
  22.   
  23.     @Override  
  24.     public int getCount() {  
  25.         return items.size();  
  26.     }  
  27.   
  28.     @Override  
  29.     public Object getItem(int arg0) {  
  30.         return items.get(arg0);  
  31.     }  
  32.   
  33.     @Override  
  34.     public long getItemId(int arg0) {  
  35.         return arg0;  
  36.     }  
  37.   
  38.     @Override  
  39.     public View getView(final int position, View view, ViewGroup arg2) {  
  40.         if(view == null) {  
  41.             view = LayoutInflater.from(ctx).inflate(R.layout.item, null);  
  42.         }  
  43.         final Item item = items.get(position);  
  44.         ImageView icon = (ImageView) view.findViewById(R.id.item_icon);  
  45.         icon.setImageResource(item.icon);  
  46.         TextView text = (TextView) view.findViewById(R.id.item_text);  
  47.         text.setText(ctx.getString(item.text));  
  48.         view.setOnClickListener(new OnClickListener() {  
  49.             @Override  
  50.             public void onClick(View v) {  
  51.                 Intent intent = new Intent();  
  52.                 intent.putExtra("id", position+1);  
  53.                 intent.putExtra("title", ctx.getString(item.text));  
  54.                 intent.setClass(ctx, MListActivity.class);  
  55.                 ctx.startActivity(intent);  
  56.             }  
  57.         });  
  58.         return view;  
  59.     }  
  60.       
  61.     static class Item {  
  62.           
  63.         public Item() {  
  64.               
  65.         }  
  66.           
  67.         public Item(int bgColor, int icon, int text) {  
  68.             super();  
  69.             this.bgColor = bgColor;  
  70.             this.icon = icon;  
  71.             this.text = text;  
  72.         }  
  73.           
  74.         public int bgColor;  
  75.         public int icon;  
  76.         public int text;  
  77.     }  
  78.   
  79. }  
其中Item为保存了背景图、分类图标和分类名称的模型对象。我们为了实现方便,将背景图忽略。MainGridAdapter为每个分类提供了单击事件,点击后将进入子分类列表:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. view.setOnClickListener(new OnClickListener() {  
  2.             @Override  
  3.             public void onClick(View v) {  
  4.                 Intent intent = new Intent();  
  5.                 intent.putExtra("id", position+1);  
  6.                 intent.putExtra("title", ctx.getString(item.text));  
  7.                 intent.setClass(ctx, MListActivity.class);  
  8.                 ctx.startActivity(intent);  
  9.             }  
  10.         });  

该Adapter使用方式如下所示:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. private void initGrid() {  
  2.         List<Item> items = new ArrayList<Item>();  
  3.         items.add(new Item(R.color.item1, R.drawable.item1, R.string.item1));  
  4.         items.add(new Item(R.color.item2, R.drawable.item2, R.string.item2));  
  5.         items.add(new Item(R.color.item3, R.drawable.item3, R.string.item3));  
  6.         items.add(new Item(R.color.item4, R.drawable.item4, R.string.item4));  
  7.         items.add(new Item(R.color.item5, R.drawable.item5, R.string.item5));  
  8.         items.add(new Item(R.color.item6, R.drawable.item6, R.string.item6));  
  9.         items.add(new Item(R.color.item7, R.drawable.item7, R.string.item7));  
  10.         items.add(new Item(R.color.item8, R.drawable.item8, R.string.item8));  
  11.         items.add(new Item(R.color.item9, R.drawable.item9, R.string.item9));  
  12.         items.add(new Item(R.color.item9, R.drawable.item10, R.string.item10));  
  13.         items.add(new Item(R.color.item9, R.drawable.item11, R.string.item11));  
  14.         items.add(new Item(R.color.item9, R.drawable.item12, R.string.item12));  
  15.         items.add(new Item(R.color.item9, R.drawable.item13, R.string.item13));  
  16.         items.add(new Item(R.color.item9, R.drawable.item14, R.string.item14));  
  17.         grid.setAdapter(new MainGridAdapter(items, this));  
  18.     }  
下面给出主界面Activity:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3. import java.util.Timer;  
  4. import java.util.TimerTask;  
  5.   
  6. import android.app.Activity;  
  7. import android.content.Intent;  
  8. import android.os.Bundle;  
  9. import android.view.KeyEvent;  
  10. import android.view.View;  
  11. import android.view.View.OnClickListener;  
  12. import android.widget.EditText;  
  13. import android.widget.GridView;  
  14. import android.widget.ImageView;  
  15. import android.widget.Toast;  
  16.   
  17.   
  18. public class MainActivity extends Activity implements OnClickListener {  
  19.       
  20.     private GridView grid;  
  21.     private ImageView clearButton, searchButton;  
  22.     private EditText input;  
  23.   
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.main);  
  28.         clearButton = (ImageView) findViewById(R.id.main_clear_btn);  
  29.         clearButton.setOnClickListener(this);  
  30.         searchButton = (ImageView) findViewById(R.id.main_search_btn);  
  31.         searchButton.setOnClickListener(this);  
  32.         input = (EditText) findViewById(R.id.main_input);  
  33.         grid = (GridView) findViewById(R.id.main_grid);  
  34.         initGrid();  
  35.     }  
  36.   
  37.     private void initGrid() {  
  38.         List<Item> items = new ArrayList<Item>();  
  39.         items.add(new Item(R.color.item1, R.drawable.item1, R.string.item1));  
  40.         items.add(new Item(R.color.item2, R.drawable.item2, R.string.item2));  
  41.         items.add(new Item(R.color.item3, R.drawable.item3, R.string.item3));  
  42.         items.add(new Item(R.color.item4, R.drawable.item4, R.string.item4));  
  43.         items.add(new Item(R.color.item5, R.drawable.item5, R.string.item5));  
  44.         items.add(new Item(R.color.item6, R.drawable.item6, R.string.item6));  
  45.         items.add(new Item(R.color.item7, R.drawable.item7, R.string.item7));  
  46.         items.add(new Item(R.color.item8, R.drawable.item8, R.string.item8));  
  47.         items.add(new Item(R.color.item9, R.drawable.item9, R.string.item9));  
  48.         items.add(new Item(R.color.item9, R.drawable.item10, R.string.item10));  
  49.         items.add(new Item(R.color.item9, R.drawable.item11, R.string.item11));  
  50.         items.add(new Item(R.color.item9, R.drawable.item12, R.string.item12));  
  51.         items.add(new Item(R.color.item9, R.drawable.item13, R.string.item13));  
  52.         items.add(new Item(R.color.item9, R.drawable.item14, R.string.item14));  
  53.         grid.setAdapter(new MainGridAdapter(items, this));  
  54.     }  
  55.       
  56.     @Override  
  57.     public void onClick(View v) {  
  58.         switch (v.getId()) {  
  59.         case R.id.main_clear_btn:  
  60.             input.setText("");  
  61.             break;  
  62.         case R.id.main_search_btn:  
  63.             String searchStr = input.getText().toString();  
  64.             if(searchStr == null || searchStr.trim().equals("")) {  
  65.                 Toast.makeText(this"请输入要搜索的菜谱!", Toast.LENGTH_SHORT).show();  
  66.             } else {  
  67.                 Intent intent = new Intent();  
  68.                 intent.putExtra("keyword", searchStr);  
  69.                 intent.setClass(this, CListActivity.class);  
  70.                 startActivity(intent);  
  71.             }  
  72.             break;  
  73.   
  74.         default:  
  75.             break;  
  76.         }  
  77.     }  
  78.       
  79. }  

子分类界面设计开发

当用户点击主界面的主分类条目时,将进入该分类的子分类列表界面。子分类接口为:http://api.yi18.net/cook/cookclass?id=myid
我们在MUtils中提供获取子分类的方法:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @SuppressWarnings("serial")  
  2.     public static ArrayList<HashMap<String, Object>> getChildClass(final int pid) {  
  3.         String url = "http://api.yi18.net/cook/cookclass";  
  4.         String result = HttpUtils.httpGet(url, new HashMap<String, Object>(){{  
  5.             put("id", pid);  
  6.         }});  
  7.         ArrayList<HashMap<String, Object>> dataMap = new  ArrayList<HashMap<String, Object>>();  
  8.         if(result != null) {  
  9.             try {  
  10.                 JSONObject root = new JSONObject(result);  
  11.                 if(root.getBoolean("success")) {  
  12.                     JSONArray datas = root.getJSONArray("yi18");  
  13.                     for(int i = 0, len = datas.length(); i < len; i++) {  
  14.                         HashMap<String, Object> data = new HashMap<String, Object>();  
  15.                         JSONObject obj = datas.getJSONObject(i);  
  16.                         data.put("id", obj.getInt("id"));  
  17.                         data.put("name", obj.getString("name"));  
  18.                         dataMap.add(data);  
  19.                     }  
  20.                 }  
  21.             } catch (Exception e) {  
  22.             }  
  23.         }  
  24.         return dataMap;  
  25.     }  

返回ArrayList<HashMap>是为了便于SimpleAdapter直接使用,使用见如下的MListActivity中的相关代码:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.util.ArrayList;  
  2. import java.util.HashMap;  
  3.   
  4. import android.app.Activity;  
  5. import android.content.Intent;  
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.os.Message;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.AdapterView;  
  12. import android.widget.AdapterView.OnItemClickListener;  
  13. import android.widget.ImageView;  
  14. import android.widget.ListView;  
  15. import android.widget.SimpleAdapter;  
  16. import android.widget.TextView;  
  17.   
  18. import com.my.lib.Utils;  
  19.   
  20. public class MListActivity extends Activity implements OnClickListener, OnItemClickListener, Runnable {  
  21.       
  22.     private ImageView unconnect;  
  23.     private ListView mlist;  
  24.     Handler handler;  
  25.     ArrayList<HashMap<String, Object>> mdata;  
  26.       
  27.     @Override  
  28.     protected void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.list);  
  31.         findViewById(R.id.list_return).setOnClickListener(this);  
  32.         mlist = (ListView) findViewById(R.id.mlist);  
  33.         mlist.setOnItemClickListener(this);  
  34.         unconnect = (ImageView) findViewById(R.id.list_unconnect);  
  35.         unconnect.setOnClickListener(this);  
  36.         ((TextView)findViewById(R.id.list_title)).setText(getIntent().getStringExtra("title"));  
  37.         handler = new Handler() {  
  38.             @Override  
  39.             public void handleMessage(Message msg) {  
  40.                 if(mdata == null) {  
  41.                     change(true);  
  42.                 } else {  
  43.                     change(false);  
  44.                     mlist.setAdapter(new SimpleAdapter(MListActivity.this, mdata, R.layout.list_item, new String[]{"name"}, new int[]{R.id.list_item_text}));  
  45.                 }  
  46.             }  
  47.         };  
  48.         new Thread(this).start();  
  49.     }  
  50.       
  51.     @Override  
  52.     @SuppressWarnings("unchecked")  
  53.     public void onItemClick(AdapterView<?> av, View v, int position, long arg3) {  
  54.         HashMap<String, Object> item = (HashMap<String, Object>)av.getItemAtPosition(position);  
  55.         Intent intent = new Intent();  
  56.         intent.putExtra("id", (Integer)item.get("id"));  
  57.         intent.putExtra("title", (String)item.get("name"));  
  58.         intent.setClass(this, CListActivity.class);  
  59.         startActivity(intent);  
  60.     }  
  61.       
  62.     @Override  
  63.     public void onClick(View v) {  
  64.         switch (v.getId()) {  
  65.         case R.id.list_return:  
  66.             MListActivity.this.finish();  
  67.             break;  
  68.         case R.id.list_unconnect:  
  69.             new Thread(this).start();  
  70.             break;  
  71.         default:  
  72.             break;  
  73.         }  
  74.     }  
  75.       
  76.     @Override  
  77.     public void run() {  
  78.         if(Utils.canAccessNetwork(MListActivity.this)) {  
  79.             mdata = MUtils.getChildClass(getIntent().getIntExtra("id"1));  
  80.         }   
  81.         handler.sendEmptyMessage(1);  
  82.     }  
  83.       
  84.     void change(boolean flag) {  
  85.         if(flag) {  
  86.             mlist.setVisibility(View.GONE);  
  87.             unconnect.setVisibility(View.VISIBLE);  
  88.         } else {  
  89.             mlist.setVisibility(View.VISIBLE);  
  90.             unconnect.setVisibility(View.GONE);  
  91.         }  
  92.     }  
  93. }  
需要注意的是:Http请求处理不能在主线程中调用,需要开启新的线程调用。子分类点击后将进入该子分类的食谱列表

分类列表布局XML如下所示:
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@drawable/list_item_bg"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <RelativeLayout  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="50dp"  
  11.         android:background="@drawable/title_bg" >  
  12.   
  13.         <ImageView  
  14.             android:id="@+id/list_return"  
  15.             android:layout_width="wrap_content"  
  16.             android:layout_height="wrap_content"  
  17.             android:layout_alignParentLeft="true"  
  18.             android:layout_centerVertical="true"  
  19.             android:layout_marginLeft="20dp"  
  20.             android:src="@drawable/arrowl" />  
  21.   
  22.         <TextView  
  23.             android:id="@+id/list_title"  
  24.             android:layout_width="wrap_content"  
  25.             android:layout_height="wrap_content"  
  26.             android:layout_centerInParent="true"  
  27.             android:textColor="@android:color/white"  
  28.             android:textSize="18sp"  
  29.             android:textStyle="bold" />  
  30.     </RelativeLayout>  
  31.   
  32.     <ListView  
  33.         android:id="@+id/mlist"  
  34.         android:layout_width="match_parent"  
  35.         android:layout_height="match_parent"  
  36.         android:scrollbars="none" >  
  37.     </ListView>  
  38.   
  39.     <ImageView  
  40.         android:id="@+id/list_unconnect"  
  41.         android:layout_marginTop="160dp"  
  42.         android:layout_gravity="center"  
  43.         android:layout_width="wrap_content"  
  44.         android:layout_height="wrap_content"  
  45.         android:src="@drawable/unconnect"   
  46.         android:visibility="gone"/>  
  47.   
  48. </LinearLayout>  

Item布局xml如下所示:
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="50dp"  
  5.     android:background="@drawable/list_selector" >  
  6.       
  7.     <ImageView  
  8.         android:id="@+id/mlist_item_icon"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_alignParentLeft="true"  
  12.         android:layout_centerVertical="true"  
  13.         android:src="@drawable/list_item_icon"  
  14.         android:layout_marginLeft="20dp"  
  15.         android:layout_marginRight="20dp" />  
  16.   
  17.     <TextView  
  18.         android:id="@+id/list_item_text"  
  19.         android:layout_width="wrap_content"  
  20.         android:layout_height="wrap_content"  
  21.         android:layout_centerVertical="true"  
  22.         android:layout_toRightOf="@+id/mlist_item_icon"  
  23.         android:textColor="@android:color/white"  
  24.         android:textSize="16sp" />  
  25.   
  26.     <ImageView  
  27.         android:id="@+id/mlist_item_arrow"  
  28.         android:layout_width="wrap_content"  
  29.         android:layout_height="wrap_content"  
  30.         android:src="@drawable/arrowr"  
  31.         android:layout_alignParentRight="true"  
  32.         android:layout_centerVertical="true"  
  33.         android:layout_marginRight="20dp" />  
  34.   
  35. </RelativeLayout>  
0 0
原创粉丝点击