thinkland001

ANDROID 开发一个新闻阅读器 4章 新闻列表-下

1.          功能描述

这一讲中我们将对上一章中已经实现新闻列表做一个功能上的强化,其中包括 返回按键, 新闻的收藏夹, 以及新闻列表的上下翻页。

下图是我们设计的样式,最上方的按钮栏这边不再多做介绍了,在原有基础上 增加了上一页,下一页 按钮。

 

界面如图:

 

 

 

 

2.          界面布局

修改之前的 news_result_list.xml 文件, 添加翻页按钮,在之前的布局里加入这2个布局:

  

1 <RelativeLayout android:id="@+id/result_RelativeLayout01"
2 android:layout_width="fill_parent"
3 android:layout_height="wrap_content"
4 android:background="@color/yellow">
5 <Button android:id="@+id/result_back"
6 android:layout_width="wrap_content"
7 android:layout_height="wrap_content"
8 android:layout_alignParentLeft="true"
9 android:paddingLeft="2dip"
10 android:text="@string/back"/>
11 // 上页按钮
12 <Button android:id="@+id/result_last_pg"
13 android:layout_width="wrap_content"
14 android:layout_height="wrap_content"
15 android:layout_toRightOf="@id/result_back"
16 android:text="@string/last_page"/>
17
18 <Button android:id="@+id/result_collection"
19 android:layout_width="wrap_content"
20 android:layout_height="wrap_content"
21 android:layout_alignParentRight="true"
22 android:paddingRight="2dip"
23 android:text="@string/collection" />
24 // 下页按钮
25 <Button android:id="@+id/result_next_pg"
26 android:layout_width="wrap_content"
27 android:layout_height="wrap_content"
28 android:layout_toLeftOf="@id/result_collection"
29 android:text="@string/next_page"/>
30  </RelativeLayout>

 

因为是在 RelativeLayout 布局下,所以 分别通过属性

 

android:layout_toRightOf="@id/result_back"

android:layout_toLeftOf="@id/result_collection"

让其位于 返回 收藏按钮的左右两侧

 

同时在 strings.xml 文件下定义 last_page next_page text 字段

    

<string name="last_page">上页</string>
<string name="next_page">下页</string>

 

 

添加按钮后的界面:

 

接下来为 上页, 下页 按钮添加响应事件:

 

 

3.          后台逻辑层


修改 newsResultListActivity.java 添加两个新的Button 控件:

public Button result_last_pg, result_next_pg;

 

findView() 方法下添加 这两个控件的资源获取方法:

1 /**
2 * 获取页面上定义的控件资源
3 */
4 public void findView(){
5
6 result_last_pg = (Button)this.findViewById(R.id.result_last_pg);
7 result_next_pg = (Button)this.findViewById(R.id.result_next_pg);
8 ......
9 ......
10 ......
11 }

 

onCreate() 方法里 增加一个监听方法的 调用,但注意一定要在执行完 findView() 方法,获取控件资源后才能执行

 

1 //为空间添加监听事件
2   setListener();

 

同时声明该方法, 并分别给按钮 result_back, result_collection, result_last_pg, result_next_pg 添加监听事件:

 

1
2  /**
3 * 设置页面上控件的监听事件
4 */
5 public void setListener(){
6 result_last_pg.setOnClickListener(new OnClickListener(){
7
8 @Override
9 public void onClick(View v) {
10 // TODO Auto-generated method stub
11  
12 }
13
14 });
15
16 result_next_pg.setOnClickListener(new OnClickListener(){
17
18 @Override
19 public void onClick(View v) {
20 // TODO Auto-generated method stub
21  
22 }
23
24 });
25
26 result_back.setOnClickListener(new OnClickListener(){
27
28 @Override
29 public void onClick(View v) {
30 onDestroy();
31 }
32
33 });
34
35 result_collection.setOnClickListener(new OnClickListener(){
36
37 @Override
38 public void onClick(View v) {
39 // TODO Auto-generated method stub
40  
41 }
42
43 });
44 }

 

创建2个文件分别是 ResultListHelpI.java ResultListHelpImpl.java 前者是接口, 后者则是接口的具体实现:

 

接口代码:

1 import java.util.List;
2  //声明一个接口 interface
3  public interface ResultListHelpI {
4 /**
5 *
6 * @Title: getCount
7 * @Description: 记录总数
8 * @return 设定文件
9 */
10 public int getCount();
11 /**
12 *
13 * @Title: nextPage
14 * @Description: 下一页
15 */
16 public void nextPage();
17 /**
18 *
19 * @Title: prePage
20 * @Description: 前一页
21 */
22 public void prePage();
23 /**
24 *
25 * @Title: gotoPage
26 * @Description: go to x page
27 * @param n
28 * 设定文件
29 */
30 public void gotoPage(int n);
31 /**
32 *
33 * @Title: setPerPage
34 * @Description: 每页显示的条数
35 * @param page
36 * 设定文件
37 */
38 public void setPerPage(int page);
39 /**
40 *
41 * @Title: getPerPage
42 * @Description: get 每页显示的条数
43 */
44 public int getPerPage();
45 /**
46 *
47 * @Title: hasNextPage
48 * @Description: 是否有下一页
49 * @return 设定文件
50 */
51 public boolean hasNextPage();
52 /**
53 *
54 * @Title: hasHeadpage
55 * @Description:是否有上一页
56 * @return 设定文件
57 */
58 public boolean hasPrepage();
59 /**
60 *
61 * @Title: getCurrentPage
62 * @Description: 当前页数
63 * @return 设定文件
64 */
65 public int getCurrentPage();
66 /**
67 *
68 * @Title: getPageNUm
69 * @Description: 获取页数
70 * @return 设定文件
71 */
72 public int getPageNum();
73 /**
74 *
75 * @Title: currentList
76 * @Description: 当前记录集
77 * @return 设定文件
78 */
79 public List<?> getCurrentList();
80 /**
81 *
82 * @Title: initList
83 * @Description: 初始化 list
84 * @param list 设定文件
85 */
86 public void initList(List<?> list);
87 }

 

接口的具体实现 代码:

 

1 import java.util.List;
2
3  public class ResultListHelpImpl implements ResultListHelpI {
4
5 // 总list
6   private List<?> list;
7 // 默认每页显示10条
8   private int perPage = 10;
9 // 默认当前页为 第一页
10   private int currentPage = 1;
11 // 默认页数 为 一页
12   private int pageNum = 1;
13 // 当前List
14   private List<?> cList;
15 // 所有数据总数
16   private int allNum;
17
18 /**
19 * 默认构造函数
20 *
21 * @Title:
22 * @Description:
23 */
24 public ResultListHelpImpl() {
25
26 }
27
28 /**
29 * 带参数的构造函数
30 *
31 * @Title:
32 * @Description:
33 * @param list
34 * 数据集
35 * @param perPage
36 * 每页显示条数
37 */
38 public ResultListHelpImpl(List<?> list, int perPage) {
39 this.list = list;
40 if (perPage >= 1) {
41 this.perPage = perPage;
42 }
43 if (list != null && list.size() > this.perPage) {
44 this.cList = list.subList(0, this.perPage - 1);
45 }
46 // 页数
47   this.allNum = this.list.size();
48 if (this.allNum % this.perPage == 0) {
49 this.pageNum = this.allNum / this.perPage;
50 } else {
51 this.pageNum = this.allNum / this.perPage + 1;
52 }
53 }
54
55 /**
56 *
57 * @Title: getCount
58 * @Description: 记录总数
59 * @return 设定文件
60 */
61
62 public int getCount() {
63 // TODO Auto-generated method stub
64   return this.allNum;
65 }
66
67 /**
68 *
69 * @Title: getCurrentPage
70 * @Description: 当前页数
71 * @return 设定文件
72 */
73
74 public int getCurrentPage() {
75 // TODO Auto-generated method stub
76   return this.currentPage;
77 }
78
79 /**
80 *
81 * @Title: getPageNum
82 * @Description: 获取总页数
83 * @return 设定文件
84 */
85
86 public int getPageNum() {
87 // TODO Auto-generated method stub
88  
89 return this.pageNum;
90 }
91
92 /**
93 *
94 * @Title: getPerPage
95 * @Description: get 每页显示的条数
96 */
97
98 public int getPerPage() {
99 // TODO Auto-generated method stub
100   return this.perPage;
101 }
102
103 /**
104 *
105 * @Title: gotoPage
106 * @Description: go to x page
107 * @param n
108 * 设定文件
109 */
110
111 public void gotoPage(int n) {
112 // TODO Auto-generated method stub
113   if (n > this.pageNum) {
114 n = this.pageNum;
115 this.currentPage = n;
116 } else {
117 this.currentPage = n;
118 }
119 }
120
121 /**
122 *
123 * @Title: hasNextPage
124 * @Description: 是否有下一页
125 * @return 设定文件
126 */
127
128 public boolean hasNextPage() {
129 // TODO Auto-generated method stub
130   this.currentPage++;
131 if (this.currentPage <= this.pageNum) {
132 return true;
133 } else {
134 this.currentPage = this.pageNum;
135 }
136 return false;
137 }
138
139 /**
140 *
141 * @Title: hasHeadpage
142 * @Description:是否有上一页
143 * @return 设定文件
144 */
145
146 public boolean hasPrepage() {
147 // TODO Auto-generated method stub
148   this.currentPage--;
149 if (this.currentPage > 0) {
150 return true;
151 } else {
152 this.currentPage = 1;
153 }
154 return false;
155 }
156 /**
157 *
158 * @Title: nextPage
159 * @Description: 下一页
160 */
161
162 public void nextPage() {
163 // TODO Auto-generated method stub
164   this.hasNextPage();
165 }
166
167 /**
168 *
169 * @Title: prePage
170 * @Description: 前一页
171 */
172
173 public void prePage() {
174 // TODO Auto-generated method stub
175   this.hasPrepage();
176 }
177
178 /**
179 *
180 * @Title: setPerPage
181 * @Description: 每页显示的条数
182 * @param page
183 * 设定文件
184 */
185
186 public void setPerPage(int page) {
187 // TODO Auto-generated method stub
188   this.perPage = page;
189 }
190
191 /**
192 *
193 * @Title: currentList
194 * @Description: 当前记录集
195 * @return 设定文件
196 */
197
198 public List<?> getCurrentList() {
199
200 if (this.currentPage == this.pageNum) {
201 this.cList = this.list.subList((this.currentPage-1) * this.perPage, this.allNum);
202 } else {
203
204 this.cList = this.list.subList((this.currentPage - 1)
205 * this.perPage, this.currentPage * (this.perPage));
206 }
207 return this.cList;
208 }
209
210 /**
211 *
212 * @Title: initList
213 * @Description: 初始化 list
214 * @param list
215 * 设定文件
216 */
217 public void initList(List<?> list) {
218
219 this.list = list;
220 if (this.perPage <= 0) {
221 this.perPage = 10;
222 }
223
224 // 页数
225   this.allNum = this.list.size();
226 if (this.allNum % this.perPage == 0) {
227 this.pageNum = this.allNum / this.perPage;
228 } else {
229 this.pageNum = this.allNum / this.perPage + 1;
230 }
231 }
232
233 }

 

 

newsResultListActivity 中定义 接口的对象:

 

    

1 private ResultListHelpImpl resultListHelpI ;

 

getWebData 类中,当返回的记录不为空的时候,我们调用接口里的方法 对其做分页的处理

 

 

1 if(dataList == null || dataList.size() == 0){
2 messageListener.sendMessage(m2);
3 return;
4 }else{
5 //每页显示10笔记录
6   resultListHelpI = new ResultListHelpImpl(dataList, 10);
7
8 currentList = new ArrayList<newsDataTO>();
9 //获取当前的记录,存入currentList中
10   currentList = (List<newsDataTO>)resultListHelpI.getCurrentList();
11 messageListener.sendMessage(m1);
12 }

 

将之前的显示方法 displayNewsResult() 中的dataList 换成做过分页处理的currentList

1 /**
2 * 将从网络上获取的数据显示在我们自定义的ListView 里面
3 */
4 public void displayNewsResult(){
5 //无返回数据信息提示 设置为不可见,这样用户就看不到页面上 '请等待' 这些提示
6   newsResultListEmptyText.setVisibility(View.GONE);
7 //
8   newsResultListAdapter newsResultAdapter = new newsResultListAdapter(currentList, mContext);
9 newsResultList.setAdapter(newsResultAdapter);
10
11 newsResultList.setOnItemClickListener(new OnItemClickListener(){
12 @Override
13 public void onItemClick(AdapterView<?> arg0, View arg1,
14 int arg2, long arg3) {
15
16 onClickItemNo =(int) ((newsDataTO)currentList.get(arg2)).getId();
17  // http://pic.think-land.com/xml.php?id=20026
18  // startLoadingDialog();
19  // Thread t1 = new Thread(new startUpdate_detail());
20  // t1.start();
21   }
22
23 });
24 }

这时候在上页,下页的监听程序中加入翻页的逻辑,如果已经是第一页或者是最后一页,则弹出提示消息

1 result_last_pg.setOnClickListener(new OnClickListener(){
2
3 @Override
4 public void onClick(View v) {
5 if(resultListHelpI != null){
6 //如果存在上一页的话, 当前页减1
7   if(!resultListHelpI.hasPrepage()) {
8 Toast.makeText(newsResultListActivity.this,"已经是第一页了",Toast.LENGTH_SHORT).show();
9 }else{
10 currentList = (List<newsDataTO>) resultListHelpI.getCurrentList();
11 displayNewsResult();
12 }
13 }
14 }
15 });
16
17 result_next_pg.setOnClickListener(new OnClickListener(){
18
19 @Override
20 public void onClick(View v) {
21 if(resultListHelpI != null){
22 //如果存在下一页的话,当前页加1
23   if(!resultListHelpI.hasNextPage()) {
24 Toast.makeText(newsResultListActivity.this,"已经是最后一页了",Toast.LENGTH_SHORT).show();
25 }else{
26 currentList = (List<newsDataTO>) resultListHelpI.getCurrentList();
27 displayNewsResult();
28 }
29 }
30 }
31 });

 

 

重载onDestory 方法,同时给返回按钮加上监听事件,点击后关闭当前页,返回到上一菜单,如下

1 //重载的方法
2  @Override
3 public void onDestroy() {
4 super.onDestroy();
5 this.finish();
6 }

 

监听事件:

1 //返回按鈕
2   result_back.setOnClickListener(new OnClickListener(){
3
4 @Override
5 public void onClick(View v) {
6 onDestroy();
7 }
8 });

完整的 newsResultListActivity.java 内的代码,如下:


newsResultListActivity
1 import java.io.InputStream;
2  import java.net.URL;
3  import java.util.ArrayList;
4  import java.util.Collections;
5  import java.util.List;
6
7  import com.thinkland.demo.mnr.common.MyNewsReaderConstant;
8  import com.thinkland.demo.mnr.common.ResultListHelpImpl;
9  import com.thinkland.demo.mnr.data.newsDataTO;
10  import com.thinkland.demo.mnr.helper.newsResultListAdapter;
11  import com.thinkland.demo.mnr.net.getWebDataHelperI;
12  import com.thinkland.demo.mnr.net.getWebDataHelperImpl;
13
14  import android.app.Activity;
15  import android.app.ProgressDialog;
16  import android.content.Context;
17  import android.content.Intent;
18  import android.os.Bundle;
19  import android.os.Handler;
20  import android.os.Message;
21  import android.view.View;
22  import android.view.View.OnClickListener;
23  import android.widget.AdapterView;
24  import android.widget.Button;
25  import android.widget.ListView;
26  import android.widget.TextView;
27  import android.widget.Toast;
28  import android.widget.AdapterView.OnItemClickListener;
29
30  public class newsResultListActivity extends Activity{
31
32 protected static final int threadS1 = 0x2311;
33 protected static final int threadF1 = 0x2312;
34
35 public String newsType = "0";
36 public List<newsDataTO> dataList;
37 public List<newsDataTO> currentList;
38 public int onClickItemNo;
39
40 public ProgressDialog pd;
41 public Button result_back, result_collection ;
42 public Button result_last_pg, result_next_pg;
43 public TextView newsResultListEmptyText; //用来显示无新闻记录,或者请用户等待 一类的提示信息
44   public ListView newsResultList; //页面的ListView控件
45  
46 public Context mContext;
47 public getWebDataHelperI gwdhI;
48 private ResultListHelpImpl resultListHelpI ;
49
50 @Override
51 public void onCreate(Bundle savedInstanceState) {
52 super.onCreate(savedInstanceState);
53 setContentView(R.layout.news_result_list);
54
55 mContext = newsResultListActivity.this;
56
57 Intent aIntent = getIntent();
58 Bundle aBundle = aIntent.getExtras();
59 if(aBundle != null){
60 //获取上一个Activity 传递过来的新闻类型参数
61   newsType = aBundle.getString(MyNewsReaderConstant.MAIN_NEWS_TYPE);
62 }
63
64 //显示一个loading框
65   startLoadingDialog();
66
67 //获取页面上定义的控件资源,包括listview
68   findView();
69
70 //为空间添加监听事件
71   setListener();
72
73 //开启一个线程用来获取网络新闻数据
74   Thread webThread = new Thread(new getWebData());
75 webThread.start();
76
77 }
78
79 /**
80 * 显示一个loading 的弹出框
81 */
82 public void startLoadingDialog(){
83
84 pd = ProgressDialog.show(newsResultListActivity.this, null, MyNewsReaderConstant.PROGRESS_ALERT_LOADING, true,true);
85 }
86
87 /**
88 * 获取页面上定义的控件资源
89 */
90 public void findView(){
91
92 result_last_pg = (Button)this.findViewById(R.id.result_last_pg);
93 result_next_pg = (Button)this.findViewById(R.id.result_next_pg);
94 result_back = (Button)this.findViewById(R.id.result_back);
95 result_collection = (Button)this.findViewById(R.id.result_collection);
96 newsResultListEmptyText = (TextView)this.findViewById(R.id.newsResultListEmptyText);
97 newsResultList = (ListView)this.findViewById(R.id.newsResultList);
98 }
99
100 /**
101 * 设置页面上控件的监听事件
102 */
103 public void setListener(){
104
105 //上頁按鈕
106   result_last_pg.setOnClickListener(new OnClickListener(){
107
108 @Override
109 public void onClick(View v) {
110 if(resultListHelpI != null){
111 //如果存在上一页的话, 当前页减1
112   if(!resultListHelpI.hasPrepage()) {
113 Toast.makeText(newsResultListActivity.this,"已经是第一页了",Toast.LENGTH_SHORT).show();
114 }else{
115 currentList = (List<newsDataTO>) resultListHelpI.getCurrentList();
116 displayNewsResult();
117 }
118 }
119 }
120 });
121
122 //下頁按鈕
123   result_next_pg.setOnClickListener(new OnClickListener(){
124
125 @Override
126 public void onClick(View v) {
127 if(resultListHelpI != null){
128 //如果存在下一页的话,当前页加1
129   if(!resultListHelpI.hasNextPage()) {
130 Toast.makeText(newsResultListActivity.this,"已经是最后一页了",Toast.LENGTH_SHORT).show();
131 }else{
132 currentList = (List<newsDataTO>) resultListHelpI.getCurrentList();
133 displayNewsResult();
134 }
135 }
136 }
137 });
138
139 //返回按鈕
140   result_back.setOnClickListener(new OnClickListener(){
141
142 @Override
143 public void onClick(View v) {
144 onDestroy();
145 }
146
147 });
148
149 //收藏书签按钮
150   result_collection.setOnClickListener(new OnClickListener(){
151
152 @Override
153 public void onClick(View v) {
154 // TODO Auto-generated method stub
155  
156 }
157
158 });
159 }
160
161
162 /**
163 * 将从网络上获取的数据显示在我们自定义的ListView 里面
164 */
165 public void displayNewsResult(){
166 //无返回数据信息提示 设置为不可见,这样用户就看不到页面上 '请等待' 这些提示
167   newsResultListEmptyText.setVisibility(View.GONE);
168 //
169   newsResultListAdapter newsResultAdapter = new newsResultListAdapter(currentList, mContext);
170 newsResultList.setAdapter(newsResultAdapter);
171
172 newsResultList.setOnItemClickListener(new OnItemClickListener(){
173 @Override
174 public void onItemClick(AdapterView<?> arg0, View arg1,
175 int arg2, long arg3) {
176
177 onClickItemNo =(int) ((newsDataTO)currentList.get(arg2)).getId();
178  // http://pic.think-land.com/xml.php?id=20026
179  // startLoadingDialog();
180  // Thread t1 = new Thread(new startUpdate_detail());
181  // t1.start();
182   }
183
184 });
185 }
186
187
188 /**
189 * 子线程, 用来获取网络新闻数据
190 */
191 public class getWebData implements Runnable{
192
193 @Override
194 public void run() {
195 Message m1 = new Message();
196 Message m2 = new Message();
197 m1.what = threadS1;
198 m2.what = threadF1;
199
200 dataList = new ArrayList<newsDataTO>();
201 boolean sendErrorMsg = false;
202
203 //searchValues 数组,用来存放网络查询参数
204   String[] searchColumns = {"type"};
205 String[] searchValues = {newsType};
206 gwdhI = new getWebDataHelperImpl();
207 dataList = gwdhI.getNewsResultListByType(searchColumns, searchValues);
208
209 if(dataList == null || dataList.size() == 0){
210 messageListener.sendMessage(m2);
211 return;
212 }else{
213 //每页显示10笔记录
214   resultListHelpI = new ResultListHelpImpl(dataList, 10);
215
216 currentList = new ArrayList<newsDataTO>();
217 //获取当前的记录,存入currentList中
218   currentList = (List<newsDataTO>)resultListHelpI.getCurrentList();
219 messageListener.sendMessage(m1);
220 }
221
222 }
223
224 }
225
226 Handler messageListener = new Handler(){
227
228 public void handleMessage(Message msg){
229 switch(msg.what){
230 case threadS1:
231 pd.dismiss(); //关闭loading框
232   displayNewsResult(); //显示新闻列表
233   break;
234 case threadF1:
235 pd.dismiss(); //关闭loading框
236
237 //todo 显示未能查询到记录的信息
238   newsResultListEmptyText.setVisibility(View.VISIBLE);
239 newsResultListEmptyText.setText(getResources().getString(R.string.serverConnectErrorMsg));
240 break;
241 }
242 }
243 };
244
245 @Override
246 public void onDestroy() {
247 super.onDestroy();
248 this.finish();
249 }
250 }
251  

 

4.     Manifest 配置

无修改

 

 

5.     运行效果

a.  点击上页或者下页时候,列表内容变化,并且一页只显示10笔记录。

 

 

 

 

 

 

  1. 点击返回按钮,返回到上一目录

 

      

程序包下载地址:http://u.115.com/file/f5f6adce29#MyNewsReader.rar

posted on 2011-04-07 14:31  thinkland001  阅读(212)  评论(0)    收藏  举报

导航