转载请注明出处:http://blog.csdn.net/einarzhang/article/details/44774635

本系列文章的重点是如何使用Android开发一个简单的健康食谱软件。使用了以下相关技术中见例如:

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

软件文件结构例如以下所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZWluYXJ6aGFuZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">


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

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

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

软件主界面设计开发

 主界面主要提供了健康食谱的主分类控件,用户能够选择自己感兴趣的分类进行食谱查看。

为了便于用户更好的找到自己须要的食谱,我们提供一个全局搜索功能,用户能够输入关键词搜索自己想要的食谱信息。如:萝卜。将载入出全部与萝卜相关的食谱


主界面终于效果图例如以下所看到的:


主界面共分为两大块:全局搜索布局和Grid分类布局,其布局xml例如以下所看到的:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/list_item_bg"
tools:context=".MainActivity" > <RelativeLayout
android:id="@+id/top_layout"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_alignParentTop="true"
android:background="@drawable/main_top" > <TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/main_title"
android:text="@string/app_name"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="18sp"
android:layout_alignParentTop="true" >
</TextView> <EditText
android:id="@+id/main_input"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:background="@drawable/edit_shape"
android:hint="@string/search_tip"
android:lines="1"
android:paddingLeft="32dp"
android:paddingRight="32dp"
android:singleLine="true"
android:textSize="16sp" >
</EditText> <ImageView
android:id="@+id/main_clear_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/main_input"
android:layout_alignLeft="@+id/main_input"
android:layout_alignTop="@+id/main_input"
android:src="@drawable/clear" /> <ImageView
android:id="@+id/main_search_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/main_input"
android:layout_alignRight="@+id/main_input"
android:layout_alignTop="@+id/main_input"
android:src="@drawable/search" >
</ImageView>
</RelativeLayout> <GridView
android:id="@+id/main_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/top_layout"
android:layout_marginTop="20dp"
android:gravity="center_horizontal"
android:numColumns="3"
android:scrollbars="none"
android:verticalSpacing="20dp" >
</GridView> </RelativeLayout>

通过 http://api.yi18.net/cook/cookclass接口能够获取到全部的主分类信息。

我们通过定制自有的MainGridAdapter实现GridView的渲染。源代码例如以下所看到的:

import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; public class MainGridAdapter extends BaseAdapter { private List<Item> items;
private Context ctx; public MainGridAdapter(List<Item> items, Context ctx) {
this.items = items;
this.ctx = ctx;
} @Override
public int getCount() {
return items.size();
} @Override
public Object getItem(int arg0) {
return items.get(arg0);
} @Override
public long getItemId(int arg0) {
return arg0;
} @Override
public View getView(final int position, View view, ViewGroup arg2) {
if(view == null) {
view = LayoutInflater.from(ctx).inflate(R.layout.item, null);
}
final Item item = items.get(position);
ImageView icon = (ImageView) view.findViewById(R.id.item_icon);
icon.setImageResource(item.icon);
TextView text = (TextView) view.findViewById(R.id.item_text);
text.setText(ctx.getString(item.text));
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("id", position+1);
intent.putExtra("title", ctx.getString(item.text));
intent.setClass(ctx, MListActivity.class);
ctx.startActivity(intent);
}
});
return view;
} static class Item { public Item() { } public Item(int bgColor, int icon, int text) {
super();
this.bgColor = bgColor;
this.icon = icon;
this.text = text;
} public int bgColor;
public int icon;
public int text;
} }

当中Item为保存了背景图、分类图标和分类名称的模型对象。

我们为了实现方便。将背景图忽略。

MainGridAdapter为每一个分类提供了单击事件。点击后将进入子分类列表:

view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("id", position+1);
intent.putExtra("title", ctx.getString(item.text));
intent.setClass(ctx, MListActivity.class);
ctx.startActivity(intent);
}
});

该Adapter使用方式例如以下所看到的:
private void initGrid() {
List<Item> items = new ArrayList<Item>();
items.add(new Item(R.color.item1, R.drawable.item1, R.string.item1));
items.add(new Item(R.color.item2, R.drawable.item2, R.string.item2));
items.add(new Item(R.color.item3, R.drawable.item3, R.string.item3));
items.add(new Item(R.color.item4, R.drawable.item4, R.string.item4));
items.add(new Item(R.color.item5, R.drawable.item5, R.string.item5));
items.add(new Item(R.color.item6, R.drawable.item6, R.string.item6));
items.add(new Item(R.color.item7, R.drawable.item7, R.string.item7));
items.add(new Item(R.color.item8, R.drawable.item8, R.string.item8));
items.add(new Item(R.color.item9, R.drawable.item9, R.string.item9));
items.add(new Item(R.color.item9, R.drawable.item10, R.string.item10));
items.add(new Item(R.color.item9, R.drawable.item11, R.string.item11));
items.add(new Item(R.color.item9, R.drawable.item12, R.string.item12));
items.add(new Item(R.color.item9, R.drawable.item13, R.string.item13));
items.add(new Item(R.color.item9, R.drawable.item14, R.string.item14));
grid.setAdapter(new MainGridAdapter(items, this));
}

以下给出主界面Activity:

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private GridView grid;
private ImageView clearButton, searchButton;
private EditText input; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
clearButton = (ImageView) findViewById(R.id.main_clear_btn);
clearButton.setOnClickListener(this);
searchButton = (ImageView) findViewById(R.id.main_search_btn);
searchButton.setOnClickListener(this);
input = (EditText) findViewById(R.id.main_input);
grid = (GridView) findViewById(R.id.main_grid);
initGrid();
} private void initGrid() {
List<Item> items = new ArrayList<Item>();
items.add(new Item(R.color.item1, R.drawable.item1, R.string.item1));
items.add(new Item(R.color.item2, R.drawable.item2, R.string.item2));
items.add(new Item(R.color.item3, R.drawable.item3, R.string.item3));
items.add(new Item(R.color.item4, R.drawable.item4, R.string.item4));
items.add(new Item(R.color.item5, R.drawable.item5, R.string.item5));
items.add(new Item(R.color.item6, R.drawable.item6, R.string.item6));
items.add(new Item(R.color.item7, R.drawable.item7, R.string.item7));
items.add(new Item(R.color.item8, R.drawable.item8, R.string.item8));
items.add(new Item(R.color.item9, R.drawable.item9, R.string.item9));
items.add(new Item(R.color.item9, R.drawable.item10, R.string.item10));
items.add(new Item(R.color.item9, R.drawable.item11, R.string.item11));
items.add(new Item(R.color.item9, R.drawable.item12, R.string.item12));
items.add(new Item(R.color.item9, R.drawable.item13, R.string.item13));
items.add(new Item(R.color.item9, R.drawable.item14, R.string.item14));
grid.setAdapter(new MainGridAdapter(items, this));
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.main_clear_btn:
input.setText("");
break;
case R.id.main_search_btn:
String searchStr = input.getText().toString();
if(searchStr == null || searchStr.trim().equals("")) {
Toast.makeText(this, "请输入要搜索的菜谱!", Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent();
intent.putExtra("keyword", searchStr);
intent.setClass(this, CListActivity.class);
startActivity(intent);
}
break; default:
break;
}
} }

子分类界面设计开发

当用户点击主界面的主分类条目时,将进入该分类的子分类列表界面。子分类接口为:http://api.yi18.net/cook/cookclass?id=myid
我们在MUtils中提供获取子分类的方法:
@SuppressWarnings("serial")
public static ArrayList<HashMap<String, Object>> getChildClass(final int pid) {
String url = "http://api.yi18.net/cook/cookclass";
String result = HttpUtils.httpGet(url, new HashMap<String, Object>(){{
put("id", pid);
}});
ArrayList<HashMap<String, Object>> dataMap = new ArrayList<HashMap<String, Object>>();
if(result != null) {
try {
JSONObject root = new JSONObject(result);
if(root.getBoolean("success")) {
JSONArray datas = root.getJSONArray("yi18");
for(int i = 0, len = datas.length(); i < len; i++) {
HashMap<String, Object> data = new HashMap<String, Object>();
JSONObject obj = datas.getJSONObject(i);
data.put("id", obj.getInt("id"));
data.put("name", obj.getString("name"));
dataMap.add(data);
}
}
} catch (Exception e) {
}
}
return dataMap;
}

返回ArrayList<HashMap>是为了便于SimpleAdapter直接使用,使用见例如以下的MListActivity中的相关代码:

import java.util.ArrayList;
import java.util.HashMap; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView; import com.my.lib.Utils; public class MListActivity extends Activity implements OnClickListener, OnItemClickListener, Runnable { private ImageView unconnect;
private ListView mlist;
Handler handler;
ArrayList<HashMap<String, Object>> mdata; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
findViewById(R.id.list_return).setOnClickListener(this);
mlist = (ListView) findViewById(R.id.mlist);
mlist.setOnItemClickListener(this);
unconnect = (ImageView) findViewById(R.id.list_unconnect);
unconnect.setOnClickListener(this);
((TextView)findViewById(R.id.list_title)).setText(getIntent().getStringExtra("title"));
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(mdata == null) {
change(true);
} else {
change(false);
mlist.setAdapter(new SimpleAdapter(MListActivity.this, mdata, R.layout.list_item, new String[]{"name"}, new int[]{R.id.list_item_text}));
}
}
};
new Thread(this).start();
} @Override
@SuppressWarnings("unchecked")
public void onItemClick(AdapterView<? > av, View v, int position, long arg3) {
HashMap<String, Object> item = (HashMap<String, Object>)av.getItemAtPosition(position);
Intent intent = new Intent();
intent.putExtra("id", (Integer)item.get("id"));
intent.putExtra("title", (String)item.get("name"));
intent.setClass(this, CListActivity.class);
startActivity(intent);
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.list_return:
MListActivity.this.finish();
break;
case R.id.list_unconnect:
new Thread(this).start();
break;
default:
break;
}
} @Override
public void run() {
if(Utils.canAccessNetwork(MListActivity.this)) {
mdata = MUtils.getChildClass(getIntent().getIntExtra("id", 1));
}
handler.sendEmptyMessage(1);
} void change(boolean flag) {
if(flag) {
mlist.setVisibility(View.GONE);
unconnect.setVisibility(View.VISIBLE);
} else {
mlist.setVisibility(View.VISIBLE);
unconnect.setVisibility(View.GONE);
}
}
}

须要注意的是:Http请求处理不能在主线程中调用,须要开启新的线程调用。子分类点击后将进入该子分类的食谱列表


分类列表布局XML例如以下所看到的:
<?

xml version="1.0" encoding="utf-8"?

>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/list_item_bg"
android:orientation="vertical" > <RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/title_bg" > <ImageView
android:id="@+id/list_return"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:src="@drawable/arrowl" /> <TextView
android:id="@+id/list_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout> <ListView
android:id="@+id/mlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" >
</ListView> <ImageView
android:id="@+id/list_unconnect"
android:layout_marginTop="160dp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/unconnect"
android:visibility="gone"/> </LinearLayout>

Item布局xml例如以下所看到的:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/list_selector" > <ImageView
android:id="@+id/mlist_item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/list_item_icon"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp" /> <TextView
android:id="@+id/list_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/mlist_item_icon"
android:textColor="@android:color/white"
android:textSize="16sp" /> <ImageView
android:id="@+id/mlist_item_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/arrowr"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="20dp" /> </RelativeLayout>




版权声明:本文博主原创文章,博客,未经同意不得转载。

Android开发实例-健康食谱应用(一)的更多相关文章

  1. Android开发实例之miniTwitter登录界面的实现

    原文: http://www.jizhuomi.com/android/example/134.html 本文要演示的Android开发实例是如何完成一个Android中的miniTwitter登录界 ...

  2. Android开发实例详解之IMF(Android SDK Sample—SoftKeyboard)

    本博前面的文章介绍了Android开发环境的搭建和模拟器的常用操作.本次,将以Android Sample中经典的SoftKeyboard项目为例,详细解析Android上一个小型项目的开发过程和注意 ...

  3. Android开发实例总结

    写一个修改密码的界面 1画界面总结: 需要弄清楚什么地方用相对布局,什么地方使用线性布局 希望这过后自己花时间去弄清楚他们内嵌的的所有组件以及组件的属性包括用法. 2逻辑总结: 逻辑描述总是那么几步的 ...

  4. Android开发实例之多点触控程序

    智能终端设备的多点触控操作为我们带来了种种炫酷体验,这也使得很多Android开发者都对多点触控程序的开发感兴趣.实际上多点触控程序的实现并不是那么遥不可及,而是比较容易.本文就主要通过一个实例具体讲 ...

  5. Android开发实例之闹钟提醒

    本实例通过TimePickerDialog时间选择对话框让用户设置闹钟.并通过AlarmManager全局定时器在指定的时间启动闹钟Activity . 程序执行效果图: 实例代码: package ...

  6. 【Android 开发实例】时间管理APP开发之数据库设计

    当然也能够先写界面什么的.可是,总认为先把数据库后台写好在写界面比較放心. 对于数据库的设计,我一開始没什么概念.甚至不知道怎样下手,一開始想着设计成几个表?有哪些字段? 最后用了两天时间,还是一无所 ...

  7. Android开发实例 Unity显示Toast

    Android中的Toast是一种简易的消息提示框. 当视图显示给用户,在应用程序中显示为浮动.和Dialog不一样的是,它永远不会获得焦点,无法被点击.用户将可能是在中间键入别的东西.Toast类的 ...

  8. Android音乐播放器的开发实例

    本文将引导大家做一个音乐播放器,在做这个Android开发实例的过程中,能够帮助大家进一步熟悉和掌握学过的ListView和其他一些组件.为了有更好的学习效果,其中很多功能我们手动实现,例如音乐播放的 ...

  9. android开发学习---基础知识学习、如何导入已有项目和开发一个电话拨号器

    一.基础知识点学习  1.Android体系结构 如图所示,android 架构分为三层: (1)最底层是linux内核,主要是各种硬件的驱动,如相机驱动(Camera Driver),闪存驱动(Fl ...

随机推荐

  1. ng-form

    form提供的属性都是用来表示表单的验证状态的,包括:$pristine(表单没有填写记录).$dirty(表单有填写记录).$valid(通过验证).$invalid(未通过验证).$error(验 ...

  2. php几个比较高级的函数

    1.传递任意数量的函数参数 我们在.NET或者JAVA编程中,一般函数参数个数都是固定的,但是PHP允许你使用任意个数的参数.下面这个示例向你展示了PHP函数的默认参数: 1 2 3 4 5 6 7 ...

  3. 2016021801 - Java内存区域学习笔记

    根据<深入理解java虚拟机>学习归纳整理学习笔记 程序计数器 用途:当前线程的字节码文件的行号指示器.(当前机场负责控制飞机降落的空管员:当前线程表示当前机场, 所执行的字节码等同于被等 ...

  4. keil对51单片机变量和函数的编译处理

    (1)初始值不是0的全局变量 在程序调到main()函数执行前,除了要进行内存清零.初始化堆栈外,还需要将全局变量的初始值加载到RAM的指定区域(编译过程中为全局变量分配的空间). (2)未初始化的局 ...

  5. ASP.NET MVC轻教程 Step By Step 6——改进表单

    上一节我们使用原始的HTML表单来完成留言功能,但是ASP.NET MVC提供了丰富的HTML辅助方法来帮助我们构建更简洁优雅的表单. Step 1. 修改Form标签 首先,我们可以使用Html.B ...

  6. [BZOJ 3564] [SHOI2014] 信号增幅仪 【最小圆覆盖】

    题目链接:BZOJ - 3564 题目分析 求最小椭圆覆盖,题目给定了椭圆的长轴与 x 轴正方向的夹角,给定了椭圆长轴与短轴的比值. 那么先将所有点旋转一个角度,使椭圆长轴与 x 轴平行,再将所有点的 ...

  7. 【HTTP】全面比较HTTP GET与POST方法

    全面比较HTTP GET与POST方法 1.       基本信息比较 属性 GET方法 POST方法 历史: 通常使用GET方法发送的数据作为URL的一部分将会被浏览器保存起来 使用POST方法提交 ...

  8. C语言常用数学函数及其用法

    转自:http://blog.sina.com.cn/s/blog_8b5a0d0001011779.html 三角函数:(所有参数必须为弧度)  1.acos 函数申明:acos  (double ...

  9. 报错java.net.SocketException: Software caused connection abort: recv failed 怎么办

    产生这个异常的原因有多种方面,单就如 Software caused 所示, 是由于程序编写的问题,而不是网络的问题引起的. 已知会导致这种异常的一个场景如下: 客户端和服务端建立tcp的短连接,每次 ...

  10. DUILIB创建不规则窗体,自定义控件(很不错的几十篇文章)

    http://blog.csdn.net/harvic880925/article/details/8925650 http://blog.csdn.net/harvic880925/article/ ...