今天事情比较多,直接入主题,这次我介绍电子书的推荐页,先上一张推荐页的截图,看下效果。
正常的思路来讲 这是一个结构比较多样的页面,特别是内容是比较动态的页面,因为推荐的内容会不定期的更换,一般这样的页面使用html5页面来处理是最佳的,可以完全兼容,而且修改容易,只需在activity中嵌入webview,url指向网页就可以了,但我个人没有服务器可以使用,所以也建不了这样的网站,所以还是使用android原生的控件来实现这个页面,有兴趣的同学可以使用静态页面加ajax的形式试试看。下面我以原生控件来实现。
具体说来我仍然使用listview作为主要的载体,然后设定不同的itemview的布局,从而组合出整个页面的构造,从上图可以看出 如果出头部标题栏之外的部分是一个listview,那我需要有4中itemview的布局来映射四种样式,这四种样式分别为:
标题型
标签型
书架型
列表型
以上四种类型的布局文件我依次写在下方:
标题型
列表型
其实书架型的布局和书架页的一行3列的布局是同一个!哈哈。有了这四种布局,我们就可以构造一个adapter 将listview绑定,当然,还需要一个与itemview绑定的数据结构,我称为ShowItemBean 主要是记录上述四种类型的itemview的数据映射,当然会有一个字段来分辨当前showitembean是那种类型,代码如下:
package com.prince.gagareader.bean;
import java.util.List;
public class ShowItemBean {
public static final int TITLE_TAG=0;
public static final int SINGEL_BOOK_TAG=1;
public static final int LIST_BOOK_TAG=2;
public static final int CATE_TAG=3;
private int type;//showItem类型
private BookBean bookBean; //单本书listview用到
private String title; //title listView 用到
private List
bookBeans; //三列书 listview 用到
private List
cateTitles; //分类展示 用到
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public BookBean getBookBean() {
return bookBean;
}
public void setBookBean(BookBean bookBean) {
this.bookBean = bookBean;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List
getBookBeans() {
return bookBeans;
}
public void setBookBeans(List
bookBeans) {
this.bookBeans = bookBeans;
}
public List
getCateTitles() { return cateTitles; } public void setCateTitles(List
cateTitles) { this.cateTitles = cateTitles; } public ShowItemBean(String title){ type = TITLE_TAG; this.title=title; } public ShowItemBean(BookBean bookBean){ type=SINGEL_BOOK_TAG; this.bookBean = bookBean; } public ShowItemBean(List
bookBeans){ type=LIST_BOOK_TAG; this.bookBeans = bookBeans; } public ShowItemBean(List
cates,int tag){ type=CATE_TAG; this.cateTitles = cates; } }
package com.prince.gagareader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.prince.gagareader.bean.BookBean;
import com.prince.gagareader.bean.CateBean;
import com.prince.gagareader.bean.ShowItemBean;
import com.prince.gagareader.util.DateProvider;
import com.prince.gagareader.util.ImageUtil;
import com.prince.gagareader.util.ImageUtil.OnPreparedImageListenner;
import com.umeng.analytics.MobclickAgent;
public class IndexActivity extends Activity{
private Handler handler;
private ListView indexLv;
private LinearLayout bottomLinear;
private IndexLvAdapter indexLvAdapter;
private Button backButton;
private Button moreCateButton;
private List
itemDateList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.index);
initHandler();
initData();
initView();
addListenner();
}
private void initData(){
itemDateList = new ArrayList
();
new Thread(new Runnable() {
@Override
public void run() {
try {
String netState = getNetWorkCate();
if(!"none".equals(netState)){
itemDateList = DateProvider.getInstance().getShowItemBeanList(true);
}else{
itemDateList = DateProvider.getInstance().getShowItemBeanList(false);
}
sendMsgBean(null, null, 2);
} catch (IOException e) {
//网络异常
e.printStackTrace();
} catch (JSONException e) {
//
e.printStackTrace();
}
}
}).start();
}
private void initHandler(){
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1: //public
MsgBean msgBean = (MsgBean)msg.obj;
String tag = msgBean.getTag();
Drawable bitmap = msgBean.getBitmap();
ImageView iv = (ImageView)indexLv.findViewWithTag(tag);
if(iv!=null){
iv.setImageDrawable(bitmap);
}
break;
case 2://数据加载完成 显示
bottomLinear.setVisibility(View.GONE);
indexLvAdapter.notifyDataSetChanged();
break;
default:
break;
}
}
};
}
private void initView(){
indexLv = (ListView)findViewById(R.id.indexLv);
bottomLinear = (LinearLayout)findViewById(R.id.bottom_linear);
indexLvAdapter = new IndexLvAdapter();
backButton = (Button)findViewById(R.id.btn_leftTop);
moreCateButton = (Button)findViewById(R.id.btn_rightTop);
}
private void addListenner(){
indexLv.setAdapter(indexLvAdapter);
backButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
IndexActivity.this.finish();
}
});
moreCateButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(IndexActivity.this, CateListActivity.class);
intent.putExtra("param","1");
startActivity(intent);
}
});
}
class IndexLvAdapter extends BaseAdapter{
@Override
public int getCount() {
return itemDateList.size();
}
@Override
public Object getItem(int arg0) {
return itemDateList.get(arg0);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ShowItemBean showItemBean = itemDateList.get(position);
int beanType = showItemBean.getType();
switch (beanType) {
case ShowItemBean.TITLE_TAG:
convertView = preparedTitleView(showItemBean);
break;
case ShowItemBean.CATE_TAG:
convertView = preparedCateView(showItemBean);
break;
case ShowItemBean.LIST_BOOK_TAG:
convertView = preparedListBookView(showItemBean);
break;
case ShowItemBean.SINGEL_BOOK_TAG:
convertView = preparedSingleBookView(showItemBean);
break;
}
return convertView;
}
public View preparedTitleView(ShowItemBean showItemBean){
View convertView=LayoutInflater.from(IndexActivity.this).inflate(R.layout.index_title_item, null);
TextView tv = (TextView)convertView.findViewById(R.id.index_title);
tv.setText(showItemBean.getTitle());
return convertView;
}
public View preparedSingleBookView(ShowItemBean showItemBean){
View convertView=LayoutInflater.from(IndexActivity.this).inflate(R.layout.single_book_item, null);
ImageView iv = (ImageView)convertView.findViewById(R.id.bookshow);
TextView name_tv = (TextView)convertView.findViewById(R.id.novel_name);
TextView author_tv = (TextView)convertView.findViewById(R.id.novel_author);
TextView des_tv = (TextView)convertView.findViewById(R.id.novel_des);
BookBean bookBean = showItemBean.getBookBean();
name_tv.setText(bookBean.getNovelName());
author_tv.setText(bookBean.getAuthor());
des_tv.setText(bookBean.getDes());
final String imgurl = bookBean.getFengmianUrl();
iv.setTag(imgurl);
ImageUtil iu = ImageUtil.getInstance();
iu.preparedImage(imgurl, new OnPreparedImageListenner() {
@Override
public void onPrepared(Drawable bitmap) {
sendMsgBean(imgurl, bitmap, 1);
}
});
final String nid = bookBean.getNid();
convertView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(IndexActivity.this,
BookDetailActivity.class);
intent.putExtra("nid", nid);
startActivity(intent);
}
});
return convertView;
}
public View preparedListBookView(ShowItemBean showItemBean){
View convertView=LayoutInflater.from(IndexActivity.this).inflate(R.layout.book_list_item, null);
ImageView iv1 = (ImageView)convertView.findViewById(R.id.bookshow1);
ImageView iv2 = (ImageView)convertView.findViewById(R.id.bookshow2);
ImageView iv3 = (ImageView)convertView.findViewById(R.id.bookshow3);
List
beans = showItemBean.getBookBeans();
final String imgurl1 = beans.get(0).getFengmianUrl();
final String imgurl2 = beans.get(1).getFengmianUrl();
final String imgurl3 = beans.get(2).getFengmianUrl();
iv1.setTag(imgurl1);
iv2.setTag(imgurl2);
iv3.setTag(imgurl3);
ImageUtil iu = ImageUtil.getInstance();
iu.preparedImage(imgurl1,new OnPreparedImageListenner() {
@Override
public void onPrepared(Drawable bitmap) {
sendMsgBean(imgurl1, bitmap, 1);
}
});
iu.preparedImage(imgurl2,new OnPreparedImageListenner() {
@Override
public void onPrepared(Drawable bitmap) {
sendMsgBean(imgurl2, bitmap, 1);
}
});
iu.preparedImage(imgurl3,new OnPreparedImageListenner() {
@Override
public void onPrepared(Drawable bitmap) {
sendMsgBean(imgurl3, bitmap, 1);
}
});
final String iv1Nid=beans.get(0).getNid();
iv1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(IndexActivity.this,
BookDetailActivity.class);
intent.putExtra("nid", iv1Nid);
startActivity(intent);
}
});
final String iv2Nid=beans.get(1).getNid();
iv2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(IndexActivity.this,
BookDetailActivity.class);
intent.putExtra("nid", iv2Nid);
startActivity(intent);
}
});
final String iv3Nid=beans.get(2).getNid();
iv3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(IndexActivity.this,
BookDetailActivity.class);
intent.putExtra("nid", iv3Nid);
startActivity(intent);
}
});
return convertView;
}
public View preparedCateView(ShowItemBean showItemBean){
View convertView=LayoutInflater.from(IndexActivity.this).inflate(R.layout.cate_item, null);
TextView tv1 = (TextView)convertView.findViewById(R.id.cate_title1);
TextView tv2 = (TextView)convertView.findViewById(R.id.cate_title2);
TextView tv3 = (TextView)convertView.findViewById(R.id.cate_title3);
TextView tv4 = (TextView)convertView.findViewById(R.id.cate_title4);
TextView tv5 = (TextView)convertView.findViewById(R.id.cate_title5);
List
tvList= new ArrayList
(); tvList.add(tv1); tvList.add(tv2); tvList.add(tv3); tvList.add(tv4); tvList.add(tv5); List
cates = showItemBean.getCateTitles(); for(int i=0;i
比较重要的是getview那部分,慢慢看,其实道理很简单 就是分类型构造不同的itemview返回。 还有一些关于图片异步加载的东西都是小知识点。另一个比较关键的问题 是showitembean的初始化问题。这里有个 DateProvider 类,这个类是用来解析数据的,以后也会有很多地方用到这个,其源码片段如下,解析的过程就是用android自带的json解析器将json文本转为对应的模型对象。道理并不负杂,这个类我在这里贴一次,以后再用到就不贴了。
package com.prince.gagareader.util;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.util.Log;
import com.prince.gagareader.bean.BookBean;
import com.prince.gagareader.bean.CateBean;
import com.prince.gagareader.bean.Const;
import com.prince.gagareader.bean.HotwordBean;
import com.prince.gagareader.bean.MuluBean;
import com.prince.gagareader.bean.ShowItemBean;
public class DateProvider {
private static DateProvider self;
public static DateProvider getInstance(){
if(self==null){
self = new DateProvider();
}
return self;
}
private DateProvider(){}
public BookBean getBookBeanByNid(String nid) throws IOException, JSONException{
FileUtil fu = FileUtil.getInstance();
String bookUrl = Const.NOVEL_INFO_URL+nid;
String bookStr = fu.getUrlContent(bookUrl);
JSONObject resultJson = new JSONObject(bookStr);
JSONObject bookJson = resultJson.getJSONArray("result").getJSONObject(0);
String author = bookJson.getString("author");
int chapterCount = bookJson.getInt("chapterCount");
String description = bookJson.getString("description");
String image = bookJson.getString("image");
String name = bookJson.getString("name");
String lastChapter = bookJson.getString("lastChapter");
String type = bookJson.getString("type");
if("".equals(image)){
image = "http://tbook.yicha.cn/timg.html?name="+URLEncoder.encode(name)+"&author="+URLEncoder.encode(author)+"&type="+URLEncoder.encode(type);
}
int state = bookJson.getInt("state");
BookBean bookBean = new BookBean(nid, name, image, author, description, lastChapter, state, chapterCount);
return bookBean;
}
public void getSBKKdata() throws IOException{
FileUtil fileUtil = FileUtil.getInstance();
String cachePath = Const.APP_TEXT_CACHE+"/sbkk";
try {
fileUtil.saveUrlContentToFile(Const.NOVEL_BD_URL, cachePath);
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
/**
* 获取随便看看内容json
* @param getFromNet
* @return
* @throws IOException
* @throws JSONException
*/
public List
getShowItemBeanList(boolean getFromNet) throws IOException, JSONException{
String cachePath = Const.APP_TEXT_CACHE+"/sbkk";
FileUtil fileUtil = FileUtil.getInstance();
File cacheFile = new File(cachePath);
boolean updateFlag = true;
if(!cacheFile.exists()){
getSBKKdata();
updateFlag = false;
}
if(updateFlag&&getFromNet){
new Thread(new Runnable() {
@Override
public void run() {
try {
getSBKKdata();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
String bd_str = fileUtil.getFileContent(cacheFile);
return parseIndexDate(bd_str);
}
public List
parseIndexDate(String bd_str) throws JSONException{
List
itemDateList = new ArrayList
();
JSONObject bd_obj = new JSONObject(bd_str);
JSONObject bout_obj = bd_obj.getJSONObject("bout");
JSONObject boy_obj = bd_obj.getJSONObject("boy");
JSONObject girl_obj = bd_obj.getJSONObject("girl");
JSONObject new_obj = bd_obj.getJSONObject("new");
JSONObject hot_obj = bd_obj.getJSONObject("hot");
JSONObject cbout_obj = bd_obj.getJSONObject("cbout");
itemDateList.add(new ShowItemBean("精品推荐"));
JSONArray bout_array = bout_obj.getJSONArray("items");
parseSingelArray(bout_array, itemDateList);
itemDateList.add(new ShowItemBean("男生最爱"));
List
cates = new ArrayList
(); cates.add(new CateBean("都市")); cates.add(new CateBean("玄幻")); cates.add(new CateBean("仙侠")); cates.add(new CateBean("武侠")); cates.add(new CateBean("游戏")); itemDateList.add(new ShowItemBean(cates, 0)); JSONArray boy_array = boy_obj.getJSONArray("items"); parseSingelArray(boy_array, itemDateList); itemDateList.add(new ShowItemBean("女生最爱")); cates = new ArrayList
(); cates.add(new CateBean("言情")); cates.add(new CateBean("穿越")); cates.add(new CateBean("青春")); cates.add(new CateBean("历史")); cates.add(new CateBean("奇幻")); itemDateList.add(new ShowItemBean(cates, 0)); JSONArray girl_array = girl_obj.getJSONArray("items"); parseSingelArray(girl_array, itemDateList); itemDateList.add(new ShowItemBean("传统文学")); JSONArray cbout_array = cbout_obj.getJSONArray("items"); parseSingelArray(cbout_array, itemDateList); itemDateList.add(new ShowItemBean("新书速递")); cates = new ArrayList
(); cates.add(new CateBean("都市","现代都市")); cates.add(new CateBean("青春","青春文学")); cates.add(new CateBean("传记","传记纪实")); cates.add(new CateBean("爱情","浪漫爱情")); cates.add(new CateBean("随笔","随笔散文")); itemDateList.add(new ShowItemBean(cates, 0)); JSONArray new_array = new_obj.getJSONArray("items"); parseSingelArray(new_array, itemDateList); itemDateList.add(new ShowItemBean("畅销图书")); cates = new ArrayList
(); cates.add(new CateBean("经典","古代经典")); cates.add(new CateBean("恐怖","恐怖灵异")); cates.add(new CateBean("影视","影视名著")); cates.add(new CateBean("励志","职场励志")); cates.add(new CateBean("历史","历史军事")); itemDateList.add(new ShowItemBean(cates, 0)); JSONArray hot_array = hot_obj.getJSONArray("items"); parseSingelArray(hot_array, itemDateList); return itemDateList; } private void parseSingelArray(JSONArray array,List
itemDateList) throws JSONException{ int i=0; List
bookList = new ArrayList
(); for(i=0;i<3&&i
getMuluBeanListByNid(String nid,boolean getFromNet) throws IOException, JSONException{ final FileUtil fu = FileUtil.getInstance(); final String muluUrl = Const.NOVEL_INDEX_URL+"&nid="+nid+"&pno=0&psize=100000"; final String filePath = Const.APP_TEXT_CACHE+"/"+nid+"/mulu"; File muluFile = new File(filePath); if(getFromNet){ fu.saveUrlContentToFile(muluUrl, filePath); } if(muluFile.exists()){ List
muluBeanList = new ArrayList
(); String muluStr = fu.getFileContent(muluFile); JSONObject muluObj = new JSONObject(muluStr); JSONArray muluArray = muluObj.getJSONArray("result"); int length = muluArray.length(); for(int i=0;i
getAllPhbBeanList(Context context){ FileUtil fu = FileUtil.getInstance(); List
phbKeyList = fu.getAssetFileContentList(context,"phb.key"); List
cateBeanList = new ArrayList
(); int size = phbKeyList.size(); for(int i=0;i
getAllTagBeanList(String url,String param) throws IOException, JSONException{ FileUtil fu = FileUtil.getInstance(); String cateBeanListResult = fu.getUrlContent(url); List
cateBeanList = new ArrayList
(); JSONObject cateBean = new JSONObject(cateBeanListResult); JSONArray cateItems = cateBean.getJSONArray("items"); int length = cateItems.length(); JSONObject cateTagItem=null; for(int i=0;i
getAllCateBeanList(String url) throws IOException, JSONException{ FileUtil fu = FileUtil.getInstance(); String cateBeanListResult = fu.getUrlContent(url); List
cateBeanList = new ArrayList
(); JSONArray cateArray = new JSONArray(cateBeanListResult); int length = cateArray.length(); for(int i=0;i
getCateListJson(String cate,int pno,int cateType) throws IOException, JSONException{ String bdUrl = ""; if(cateType==0){ bdUrl = Const.NOVEL_BD_CATE+"&cate="+URLEncoder.encode(cate)+"&pno="+pno; }else if(cateType==1){ bdUrl = Const.NOVEL_TBD_CATE+"&cate="+URLEncoder.encode(cate)+"&pno="+pno; }else if(cateType==2){ bdUrl = Const.NOVEL_TAG_CATE+"&cate="+URLEncoder.encode(cate)+"&pno="+pno; }else{ return getCateListFromPhb(cate,pno,cateType); } FileUtil fu = FileUtil.getInstance(); String bdResult = fu.getUrlContent(bdUrl); List
bookBeanList=new ArrayList
(); if(bdResult.equals("[\"no result\"]"))return bookBeanList; JSONObject bdObj = new JSONObject(bdResult); JSONArray bdArray = bdObj.getJSONArray("record"); int length = bdArray.length(); for(int i=0;i
resultList = new ArrayList
(); JSONArray resultJsonArray = resultJson.getJSONArray("result"); int length = resultJsonArray.length(); for(int i=0;i
getHotwordBeanList() throws IOException, JSONException{ String hotwordUrl = Const.NOVEL_HOT_URL; FileUtil fu = FileUtil.getInstance(); String hotResult = fu.getUrlContent(hotwordUrl); JSONObject hotJson = new JSONObject(hotResult); List
hotBeanList = new ArrayList
(); JSONArray hotJsonArray = hotJson.getJSONArray("record"); int length = hotJsonArray.length(); for(int i=0;i
=length){ break; } String rigthWord = hotJsonArray.getString(i); HotwordBean hotwordBean = new HotwordBean(leftWord, rigthWord); hotBeanList.add(hotwordBean); } return hotBeanList; } }
而对于数据源的问题,我都封装到一个名为Const的类中,Const中,有各种数据接口的请求链接,这个类由于数据源保密性不能贴出来,大家可以从一些小说源站上寻找接口作为自己的数据源。然后封装自己的解析类。
以上就是推荐页的全部内容,肯定有地方我没讲清楚,因为写到这里我都不知所云了,哈哈,有问题可以留言给我!下一篇我们讲简介页!