我们已经实现了侧滑菜单的切换与toolbar菜单根据不同页面显示不同工具的功能,今天我们就来完成首页的显示。知乎首页有这么几个功能:

1,列表功能,信息是以列表的形式展示出来的

2,列表要能实现下拉刷新,上拉加载的功能

3,图片与文字并存

4,点击其中一项的不同区域,会跳到不同的详细页面,点击标题会跳动到一个页面,点击下面信息概要又会跳到另一个页面

好,我们就来实现这四个功能。
     这里的信息,我是通过读取服务器上webService传过来的json数据,进行解析来当信息源的。所以我们先要把信息源从服务器读出来,才能进行下面的操作。在做这之前,我们先看一下这个首页都有哪些项,有一个用户的图片,一个标题,一个信息的大小,和信息的内容。为了能更好的进行将信息读取,我们先建一个model类,把相关的字段先加上。代码如下:

IndexList.Java

[java] view plaincopy
  1. /**
  2. * 用于显示在index_fragment中ListView的内容
  3. * Created by cg on 2015/10/29.
  4. */
  5. public class IndexList {
  6. private int questionID;                                                  //问题ID
  7. private String questionTitle;                                            //问题标题
  8. private String questionSize;                                             //问题点在字节数
  9. private String questionContent;                                          //问题内容
  10. private String userPic;                                                  //发问者头像
  11. public IndexList() {
  12. }
  13. public IndexList(int questionID, String questionTitle, String questionSize, String questionContent, String userPic) {
  14. this.questionID = questionID;
  15. this.questionTitle = questionTitle;
  16. this.questionSize = questionSize;
  17. this.questionContent = questionContent;
  18. this.userPic = userPic;
  19. }
  20. public int getQuestionID() {
  21. return questionID;
  22. }
  23. public void setQuestionID(int questionID) {
  24. this.questionID = questionID;
  25. }
  26. public String getQuestionTitle() {
  27. return questionTitle;
  28. }
  29. public void setQuestionTitle(String questionTitle) {
  30. this.questionTitle = questionTitle;
  31. }
  32. public String getQuestionSize() {
  33. return questionSize;
  34. }
  35. public void setQuestionSize(String questionSize) {
  36. this.questionSize = questionSize;
  37. }
  38. public String getQuestionContent() {
  39. return questionContent;
  40. }
  41. public void setQuestionContent(String questionContent) {
  42. this.questionContent = questionContent;
  43. }
  44. public String getUserPic() {
  45. return userPic;
  46. }
  47. public void setUserPic(String userPic) {
  48. this.userPic = userPic;
  49. }
  50. }

好,model类我们建好了,现在我们就要从webServies开始取数据了,android读取webServies有很多好的第三方插件,这里我使用的是Ksoap2-android,它的使用网上有很多,我就不多说了,https://github.com/simpligility/ksoap2-android可以去下载,下载之后,我们引入jar.因为这里面我们需要一些常用的变量值,比如说地址什么的,所以我使用一个class,来存这些常用变量
configStatic.java

[java] view plaincopy
  1. /**
  2. * 常量信息
  3. * Created by cg on 2015/10/29.
  4. */
  5. public class configStatic {
  6. /**
  7. * webServies地址的命名空间,域名
  8. */
  9. public static String WEBSERVIESNAMESPACE = "http://tempuri.org/";
  10. /**
  11. * webServies明确地址
  12. */
  13. public static String WEBSERVIESURL = "http://192.168.0.163:8090/webServices/questionInfo.asmx";
  14. /**
  15. *  webServices的方法名_用来提取10条问题
  16. */
  17. public static String WEBSERVICES_INDEXLIST = "getQuestionList";
  18. }
    这里的地址是我本地的地址,下面是它传回来的数据格式:
[html] view plaincopy
  1. [{"questionID":28,"questionTitle":"苍井空老师的个人简介","questionSize":"387","questionContent":"\r\n 苍井空,1983年11月11日出生于日本东京。日本AV女演员、
  2. 成人模特,兼电视、电影演员。日本女子组合惠比寿麝香葡萄的初代首领,现成员、OG首领。2010年3月毕业并将组合首领之位交托给麻美由真,同年10月复归。
  3. \r\n 入行前曾是泳装写真女星,2002年进入AliceJapan公司,开始性感影片的拍摄生涯。因为其“童颜巨乳”的特色,开始获得人气,并连续在2003年及2004年蝉联日本
  4. 《VideoBoy》杂志年度性感女艺人第一名。[1] 从2003年起,开始参加一般电视戏剧及综艺节目中演出,[2] 2004年11月移籍到S1,成功转型,大牌杂志模特及电影演员。
  5. \r\n","userPic":"http://imgcdn.kdnet.net/UploadSmall/2013/07/21/137438445351976.jpg"},{"questionID":27,"questionTitle":"波多野结衣的故事",
  6. "questionSize":"679","questionContent":"波多野结衣(はたの ゆい),女,1988年5月24日出生于日本京都府,著名日本女演员、AV女优。
  7. 2008年,波多野结衣开始从事AV出演,并于11月加入H.M.P公司,成为H.M.P的素人,不久便被H.M.P公司雪藏,随后在BeFree公司发行过两部影片,
  8. 又转投ATTACKER公司,后又签约SKY HIGH公司。2012年,波多野结衣出席第九届上海国际成人展开幕和第二届台湾成人博览会。",
  9. "userPic":"http://img1.imgtn.bdimg.com/it/u=1823077414,3028399801\u0026fm=21\u0026gp=0.jpg"}]
好,我们来看一下,如何读取这个webService:
webservicesUntils.java
[java] view plaincopy
  1. import org.ksoap2.SoapEnvelope;
  2. import org.ksoap2.serialization.SoapObject;
  3. import org.ksoap2.serialization.SoapSerializationEnvelope;
  4. import org.ksoap2.transport.HttpTransportSE;
  5. import org.xmlpull.v1.XmlPullParserException;
  6. import java.io.IOException;
  7. /**
  8. * webservice 操作类
  9. * Created by cg on 2015/10/29.
  10. */
  11. public class webservicesUntils {
  12. private static SoapObject rpc = null;
  13. private static SoapSerializationEnvelope envelope = null;
  14. private static HttpTransportSE ht = null;
  15. /**
  16. * 调用问题信息
  17. * @param strWhere      查询条件
  18. * @param orderby       排序字段
  19. * @param startIndex    开始记录数
  20. * @param endIndex      结束记录数
  21. * @return
  22. * @throws Exception
  23. */
  24. public static String getIndexItemList(final String strWhere,final String orderby,final int startIndex,final int endIndex) throws IOException, XmlPullParserException, IOException, XmlPullParserException {
  25. rpc = new SoapObject(configStatic.WEBSERVIESNAMESPACE, configStatic.WEBSERVICES_INDEXLIST);
  26. // 设置调用方法参数的值
  27. rpc.addProperty("strWhere", strWhere);
  28. rpc.addProperty("orderby", orderby);
  29. rpc.addProperty("startIndex", startIndex);
  30. rpc.addProperty("endIndex",endIndex);
  31. // 生成调用Webservice方法的SOAP请求信息
  32. envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12);         //这里要注意,这里是webService的版本号,一般是10,11,12这三个值,如果你不确定,可以每个都试一下
  33. envelope.bodyOut = rpc;
  34. envelope.dotNet = true;
  35. envelope.setOutputSoapObject(rpc);
  36. // 创建HttpTransportSE对象,通过HttpTransportSE类的构造方法可以指定WebService的url
  37. ht = new HttpTransportSE(configStatic.WEBSERVIESURL);
  38. ht.debug = true;
  39. // 使用call方法调用WebService方法
  40. ht.call(null, envelope);
  41. String result = "0";
  42. //检查ht.call是否运行
  43. //Log.e("city", strWhere + startIndex + endIndex);
  44. // 判断取到的值是否为空
  45. if(envelope.getResponse() == null) {
  46. result = "0";
  47. }else{
  48. result = envelope.getResponse().toString();
  49. }
  50. return result;
  51. }
  52. }
要想让它好用,我们还要给它添加
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />权限这里就不多说了,上面的注解比较清楚,通过webservice我们已经把要得到的数据取回来了,接下来,我们就要把数据显示出来。这种列表形式的显示我们一般都是采用ListView控件来展示,可是我们结合第二点的需求,就是需求一个上拉和下拉的需求,这个功能ListView是没有,我们只能继承ListView自己写控件,可是自己写有点麻烦了,还好有这方面的第三插件,当然了,google也发布了一个官方的SwipeRefreshLayout插件,虽然很不错,可是它只有下拉刷新,没有上拉加载的功能。所以这里我们使用PullToRefreshListView控件,https://github.com/chrisbanes/Android-PullToRefresh,大家可以去这里下载,可惜的是,它没有给android studio提供直接加载的链接,我们直接采用加载project的方式,来加载它。好了,我们来修改一下我们之前的fragment_index.xml文件
[html] view plaincopy
  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. <!--
  6. ptr:ptrMode:PullToRefreshListView设置向上拉刷新还是向下拉刷新模式
  7. PULL_FROM_END: 下拉刷新
  8. PULL_FROM_START: 上拉加载
  9. both: 下拉刷新和上拉加载都有
  10. -->
  11. <com.handmark.pulltorefresh.library.PullToRefreshListView
  12. xmlns:ptr="http://schemas.android.com/apk/res-auto"
  13. android:id="@+id/pullrefresh_index_list"
  14. android:layout_width="fill_parent"
  15. android:layout_height="fill_parent"
  16. android:cacheColorHint="#00000000"
  17. android:divider="@color/grey"
  18. android:dividerHeight="1dp"
  19. android:fadingEdge="none"
  20. android:fastScrollEnabled="false"
  21. android:footerDividersEnabled="false"
  22. android:headerDividersEnabled="false"
  23. android:smoothScrollbar="true"
  24. ptr:ptrMode="both">
  25. </com.handmark.pulltorefresh.library.PullToRefreshListView>
  26. </LinearLayout>
PullToRefreshListView控件的使用与ListView控件的使用大体相当,没什么特别的地方,就是加载Adapter然后显示出来,但是它多了两个方法,
[java] view plaincopy
  1. public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
  2. // 模拟加载任务
  3. }
  4. @Override
  5. public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
  6. }

是用来实现上拉加载,下拉刷新的,而且都是要通过异步来进行加载的。好了,我们来修改一下首页的java代码吧
[java] view plaincopy
  1. import android.app.ProgressDialog;
  2. import android.os.Bundle;
  3. import android.os.Handler;
  4. import android.os.Message;
  5. import android.support.v4.app.Fragment;
  6. import android.util.Log;
  7. import android.view.LayoutInflater;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.widget.ListView;
  11. import android.widget.Toast;
  12. import com.example.cg.zhihu_one.untils.netUntils;
  13. import com.example.cg.zhihu_one.untils.webservicesUntils;
  14. import com.handmark.pulltorefresh.library.PullToRefreshBase;
  15. import com.handmark.pulltorefresh.library.PullToRefreshListView;
  16. /**
  17. * 首页
  18. * Created by cg on 2015/10/27.
  19. */
  20. public class IndexFragment extends Fragment {
  21. //定义信息等等控件
  22. private ProgressDialog myProgressDialog;
  23. private PullToRefreshListView pullrefresh_index_list;                       //定义信息列表
  24. @Override
  25. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  26. Bundle savedInstanceState) {
  27. View view = inflater.inflate(R.layout.fragment_index,container,false);
  28. initControls(view);
  29. return view;
  30. }
  31. /**
  32. * 对下拉列表控件进行初始化,并初始化进度控件
  33. * @param view
  34. */
  35. private void initControls(View view) {
  36. pullrefresh_index_list = (PullToRefreshListView)view.findViewById(R.id.pullrefresh_index_list);
  37. //初始化数据
  38. initDatas();
  39. // 设置下拉和上拖监听事件
  40. pullrefresh_index_list
  41. .setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {
  42. @Override
  43. public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
  44. // 模拟加载任务
  45. //new GetDownDataTask().execute();
  46. }
  47. @Override
  48. public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
  49. //Log.e("onPullUpToRefresh","有反应没有啊");
  50. //new GetUpDataTask().execute();
  51. }
  52. });
  53. }
  54. /**
  55. * 初始时,加载10条数据上来
  56. */
  57. private void initDatas()
  58. {
  59. if(netUntils.isNetworkAvailable(getActivity())) {
  60. // 初始化数据和数据源
  61. myProgressDialog = new ProgressDialog(getActivity());
  62. myProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);  //设置风格为圆形进度条
  63. myProgressDialog.setTitle("提示");                                 //设置标题
  64. myProgressDialog.setMessage("数据加载中,请稍等...");                 //设置内容
  65. myProgressDialog.setIndeterminate(false);                         //设置进度是否为不明确
  66. myProgressDialog.setCancelable(true);                             //设置进度条是否可以按退回键取消
  67. myProgressDialog.show();
  68. new Thread(new Runnable() {
  69. @Override
  70. public void run() {
  71. Message msg = new Message();
  72. try {
  73. String soapObject = webservicesUntils.getIndexItemList("", "", 1, 10);
  74. Log.e("soapObject",soapObject);
  75. msg.arg1 = 1;
  76. handler.sendMessage(msg);
  77. } catch (Exception ex) {
  78. msg.arg1 = 2;
  79. }
  80. }
  81. }).start();
  82. }else
  83. {
  84. Toast.makeText(getActivity(), "请检查您的网络是否打开!", Toast.LENGTH_LONG).show();
  85. }
  86. }
  87. Handler handler = new Handler(){
  88. @Override
  89. public void handleMessage(Message msg) {
  90. if(msg.arg1==1)
  91. {
  92. //Log.e("")
  93. }else
  94. {
  95. Toast.makeText(getActivity(), "数据读取失败!", Toast.LENGTH_LONG).show();
  96. }
  97. myProgressDialog.dismiss();
  98. }
  99. };
  100. }
   简单对程序说一下,这里我们只是简单的实现了一下把webservices中的数据取到,然后用log的方式显示出来,并没有对PullToRefreshListView进行设置什么,因为从网络中读取数据,这是需要时间的,所以我们采用了handle的方式。为了给用户一个更好的用户体验,我们加入了ProgressDialog控件,来显示等待的时间。   我们运行一下,你会发现,我们可以在logcat中显示出相应的信息了。   好,这说明我们的数据读取成功了,下面我们来设置一下列表中各item的布局和为PullToRefreshListView编写一个adapter.   在编写布局之前,我要说明一点,以前我们在做web程序的时候,图片我们都是在数据库中存取的图片地址,而不是采用二进制的形式把图片存在数据库中,这里我们也是采用这种方式,我们去看刚才我给的数据格式,我们的图片,也是一个网络地址,这样的话,就需要我们把这个网络图片显示出来,显示网络图片,用我们常用的ImageView是不行了,处非我们把图片下载到本地,然后再进行加载。现在有一个非常好用的volley,为我们提供了网络加载图片的功能。下面这个blog. http://blog.csdn.net/guolin_blog/article/details/17482095,一共是四篇,非常详细的介绍了它的使用,下载地址:http://download.csdn.net/detail/sinyu890807/7152015这里我们用到的是就是其中的NetworkImageView。先把volley.jar导入我们的程序。好了,我们来看一下,item的布局文件fragment_index_list_item.xml
[html] view plaincopy
  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:orientation="vertical">
  6. <RelativeLayout
  7. android:layout_width="fill_parent"
  8. android:layout_height="wrap_content"
  9. android:layout_marginTop="5dp"
  10. android:layout_marginBottom="5dp"
  11. android:layout_marginLeft="5dp"
  12. android:layout_marginRight="5dp">
  13. <TextView
  14. android:id="@+id/txt_index_item_Cate"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:text="热门话题"
  18. android:textSize="@dimen/list_remark_size"
  19. android:textColor="@color/gray"/>
  20. <com.android.volley.toolbox.NetworkImageView
  21. android:id="@+id/netimg_index_item_userpic"
  22. android:layout_width="30dp"
  23. android:layout_height="30dp"
  24. android:src="@drawable/img_empty_followers"
  25. android:layout_alignParentRight="true"
  26. />
  27. </RelativeLayout>
  28. <LinearLayout
  29. android:id="@+id/linear_index_item_title"
  30. android:layout_width="fill_parent"
  31. android:layout_height="wrap_content"
  32. android:layout_marginTop="5dp"
  33. android:layout_marginBottom="5dp"
  34. android:layout_marginLeft="5dp"
  35. android:layout_marginRight="5dp"
  36. android:cacheColorHint="#00000000">
  37. <TextView
  38. android:id="@+id/txt_index_item_title"
  39. android:layout_width="fill_parent"
  40. android:layout_height="wrap_content"
  41. android:text=" "
  42. android:textColor="@color/black"
  43. android:textSize="@dimen/ActionBar_title_size"
  44. />
  45. </LinearLayout>
  46. <LinearLayout
  47. android:id="@+id/linear_index_item_content"
  48. android:layout_width="fill_parent"
  49. android:layout_height="wrap_content"
  50. android:layout_marginTop="5dp"
  51. android:layout_marginBottom="5dp"
  52. android:layout_marginLeft="5dp"
  53. android:layout_marginRight="5dp"
  54. android:cacheColorHint="#00000000"
  55. android:background="@drawable/index_list_item_background">
  56. <TextView
  57. android:id="@+id/txt_index_item_size"
  58. android:layout_width="0dp"
  59. android:layout_height="wrap_content"
  60. android:layout_weight="1"
  61. android:duplicateParentState="true"
  62. android:background="@drawable/index_list_item_sizebacground"
  63. android:text="1324K"
  64. android:textSize="@dimen/list_remark_size"
  65. android:textColor="@drawable/index_list_item_sizetextcolor"
  66. android:layout_marginRight="5dp"
  67. android:gravity="center"
  68. android:layout_marginTop="2dp"
  69. />
  70. <TextView
  71. android:id="@+id/txt_index_item_content"
  72. android:layout_width="0dp"
  73. android:layout_height="wrap_content"
  74. android:text=" "
  75. android:textSize="@dimen/list_remark_size"
  76. android:textColor="@drawable/index_list_item_contexttextcolor"
  77. android:duplicateParentState="true"
  78. android:lines="3"
  79. android:ellipsize = "end"
  80. android:layout_weight="8"
  81. />
  82. </LinearLayout>
  83. </LinearLayout>
   在这里,我为内容布局设置了动态背景还把文字颜色也设置成了动态的,这个是为了在用户点击的时候,达到相应的变化。虽然这个对于功能来说并没有什么卵用。   在drawable/index_list_item_background.xml 代码:
[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3. <item
  4. android:state_activated="true"
  5. android:drawable="@color/titleBlue"
  6. />
  7. <item
  8. android:state_focused="false"
  9. android:state_pressed="true"
  10. android:drawable="@color/titleBlue" />
  11. <item android:drawable="@android:color/transparent" />
  12. </selector>
index_list_item.sizebacground.xml
<?xml version="1.0" encoding="utf-8" ?><selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 没有焦点时的背景图片 -->    <item android:state_window_focused="false" android:drawable="@color/titleBlue" />

    <item android:state_focused="false" android:state_pressed="true"   android:drawable="@color/white" />    <!-- 默认时的背景图片-->    <item android:drawable="@color/white" /></selector>
    这里要注意一点的是,我们一般喜欢设置一下默认的背景图片或是颜色,这里一定要把这个默认的值放在最下面,不然上面的所有变化就都不好用。
index_list_item.contexttextcolor.xml
[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3. <!-- 没有焦点时的背景图片 -->
  4. <item android:state_window_focused="false" android:color="@color/gray" />
  5. <item android:state_focused="false" android:state_pressed="true"   android:color="@color/white" />
  6. <!-- 默认时的背景图片-->
  7. <item android:color="@color/gray" />
  8. </selector>
index_list_item_sizetextcolor.xml
[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  3. <!-- 没有焦点时的背景图片 -->
  4. <item android:state_window_focused="false" android:color="@color/white" />
  5. <item android:state_focused="false" android:state_pressed="true"   android:color="@color/titleBlue" />
  6. <!-- 默认时的背景图片-->
  7. <item android:color="@color/white" />
  8. </selector>
    好,item布局文件搞定,我们来看一下Adapter的代码:
Index_lv_Adapter.java
[java] view plaincopy
  1. import android.content.Context;
  2. import android.graphics.Bitmap;
  3. import android.view.LayoutInflater;
  4. import android.view.View;
  5. import android.view.ViewGroup;
  6. import android.widget.BaseAdapter;
  7. import android.widget.LinearLayout;
  8. import android.widget.TextView;
  9. import com.android.volley.RequestQueue;
  10. import com.android.volley.toolbox.ImageLoader;
  11. import com.android.volley.toolbox.NetworkImageView;
  12. import com.android.volley.toolbox.Volley;
  13. import com.example.cg.zhihu_one.R;
  14. import com.example.cg.zhihu_one.models.IndexList;
  15. import com.example.cg.zhihu_one.untils.imagesUntils;
  16. import java.util.List;
  17. /**
  18. * 首页信息列表Adapter
  19. * Created by cg on 2015/10/30.
  20. */
  21. public class Index_lv_Adapter extends BaseAdapter {
  22. private List<IndexList> list_index;                                  //定义显示的信息列表
  23. private LayoutInflater inflater;
  24. //定义volley
  25. private RequestQueue mQueue;
  26. private ImageLoader imageLoader;
  27. private Context context;
  28. public Index_lv_Adapter(Context context,List<IndexList> list_index) {
  29. this.context = context;
  30. this.inflater = LayoutInflater.from(context);
  31. this.list_index = list_index;
  32. mQueue = Volley.newRequestQueue(context);
  33. imageLoader = new ImageLoader(mQueue,new imagesUntils.BitmapCache(){
  34. @Override
  35. public Bitmap getBitmap(String s) {
  36. return null;
  37. }
  38. @Override
  39. public void putBitmap(String s, Bitmap bitmap) {
  40. }
  41. });
  42. }
  43. @Override
  44. public int getCount() {
  45. return list_index.size();
  46. }
  47. @Override
  48. public Object getItem(int position) {
  49. return list_index.get(position);
  50. }
  51. @Override
  52. public long getItemId(int position) {
  53. return position;
  54. }
  55. @Override
  56. public View getView(final int position, View convertView, ViewGroup parent) {
  57. final index_list_info listclass;
  58. if(convertView==null)
  59. {
  60. listclass = new index_list_info();
  61. convertView = inflater.inflate(R.layout.fragment_index_list_item,null,false);
  62. listclass.userpic = (NetworkImageView)convertView.findViewById(R.id.netimg_index_item_userpic);
  63. listclass.item_title = (TextView)convertView.findViewById(R.id.txt_index_item_title);
  64. listclass.item_size = (TextView)convertView.findViewById(R.id.txt_index_item_size);
  65. listclass.item_content = (TextView)convertView.findViewById(R.id.txt_index_item_content);
  66. listclass.linear_index_item_title = (LinearLayout)convertView.findViewById(R.id.linear_index_item_title);
  67. listclass.linear_index_item_content = (LinearLayout)convertView.findViewById(R.id.linear_index_item_content);
  68. convertView.setTag(listclass);
  69. }
  70. else
  71. {
  72. listclass = (index_list_info)convertView.getTag();
  73. }
  74. //为图片控件加载图片,采用NetworkImageView控件。
  75. //第一项是加载图片控件的默认图片,一般是图片加载中,这样的图片
  76. //第二项是当发生错误的时候加载的图片,如网络图片路径不对或是加载失败的时候显示的图片
  77. //第三项就是加载网络图片了
  78. listclass.userpic.setDefaultImageResId(R.drawable.img_empty_followers);
  79. listclass.userpic.setErrorImageResId(R.drawable.img_empty_followers);
  80. listclass.userpic.setImageUrl(list_index.get(position).getUserPic(), imageLoader);
  81. listclass.item_title.setText(list_index.get(position).getQuestionTitle());
  82. listclass.item_size.setText(list_index.get(position).getQuestionSize());
  83. listclass.item_content.setText(list_index.get(position).getQuestionContent());
  84. // 只所以在这里添加点击事件,而不是为控件添加onitemclistener事件,
  85. // 是因为,在一个item里,点击上半部分和下半部分将要跳转的页面不同
  86. listclass.linear_index_item_content.setOnClickListener(new View.OnClickListener() {
  87. @Override
  88. public void onClick(View v) {
  89. /*Intent cIntent = new Intent();
  90. cIntent.setClass(context, Index_detailActivity.class);
  91. cIntent.putExtra("questionID", list_index.get(position).getQuestionID());
  92. cIntent.putExtra("questionTitle",list_index.get(position).getQuestionTitle());
  93. context.startActivity(cIntent);*/
  94. }
  95. });
  96. return convertView;
  97. }
  98. public class index_list_info
  99. {
  100. NetworkImageView userpic;
  101. TextView item_title;
  102. TextView item_size;
  103. TextView item_content;
  104. LinearLayout linear_index_item_title;
  105. LinearLayout linear_index_item_content;
  106. }
  107. }
   这里我把volley处理图片,防止OOM的代码单独拿出来,放到一个公共类里面,供以后的程序的调用。
[java] view plaincopy
  1. imagesUntils.java
  2. import android.graphics.Bitmap;
  3. import android.graphics.BitmapFactory;
  4. import android.util.LruCache;
  5. import com.android.volley.toolbox.ImageLoader;
  6. /**
  7. * 各种对图片进行操作的通用方法
  8. * Created by cg on 2015/10/30.
  9. */
  10. public class imagesUntils {
  11. /**
  12. * 显示保存在手机中的图片,加入了缩小图片的功能,防止OOM
  13. *
  14. * @param imgPath            文件路径
  15. * @param screenWidth        手机宽
  16. * @param screenHeight       手机高
  17. * @return                   Bitmap类型
  18. */
  19. public static Bitmap viewPic(String imgPath,int screenWidth,int screenHeight)
  20. {
  21. BitmapFactory.Options options = new BitmapFactory.Options();
  22. options.inJustDecodeBounds = true;                                //不去真的解析图片 获取图片头部信息
  23. Bitmap mitmap = BitmapFactory.decodeFile(imgPath, options);       //取得图片的信息
  24. int height = options.outHeight;                                   //图片的高
  25. int width = options.outWidth;                                     //图片的宽
  26. // 得到手机屏幕宽高比
  27. int scaleX=width/screenHeight;
  28. int scaleY=height/screenWidth;
  29. int scale=1;                                                      //默认缩小比例是1
  30. // 如果高的比例大,并且比例大于1,也就是图片的高要大于手机的高
  31. if(scaleX>scaleY && scaleY>=1)
  32. {
  33. scale=scaleX;
  34. }
  35. if(scaleY>scaleX && scaleX>=1)
  36. {
  37. scale=scaleY;
  38. }
  39. options.inJustDecodeBounds=false;                                  //真的去解析图片
  40. options.inSampleSize=scale;                                        //按比例缩小图片
  41. Bitmap bm = BitmapFactory.decodeFile(imgPath, options);
  42. return bm;
  43. }
  44. /**
  45. * 对图片进行防OOM处理
  46. */
  47. public static class BitmapCache implements ImageLoader.ImageCache{
  48. private LruCache<String,Bitmap> mCache;
  49. public BitmapCache(){
  50. int maxSize = 10*1024*1024;
  51. mCache = new LruCache<String, Bitmap>(maxSize){
  52. protected int sizeOf(String key,Bitmap bitmap)
  53. {
  54. return bitmap.getRowBytes() * bitmap.getHeight();
  55. }
  56. };
  57. }
  58. @Override
  59. public Bitmap getBitmap(String url) {
  60. return mCache.get(url);
  61. }
  62. @Override
  63. public void putBitmap(String url, Bitmap bitmap) {
  64. mCache.put(url,bitmap);
  65. }
  66. }
  67. }

Adapter程序完成,我们来修改首页的程序,为PullToRefreshListView控件绑定数据。修改后的代码如下:

[java] view plaincopy
  1. import android.app.ProgressDialog;
  2. import android.os.AsyncTask;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Message;
  6. import android.support.v4.app.Fragment;
  7. import android.view.LayoutInflater;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.widget.ListView;
  11. import android.widget.Toast;
  12. import com.example.cg.zhihu_one.Adapters.Index_lv_Adapter;
  13. import com.example.cg.zhihu_one.models.IndexList;
  14. import com.example.cg.zhihu_one.untils.netUntils;
  15. import com.example.cg.zhihu_one.untils.webservicesUntils;
  16. import com.handmark.pulltorefresh.library.PullToRefreshBase;
  17. import com.handmark.pulltorefresh.library.PullToRefreshListView;
  18. import org.json.JSONArray;
  19. import org.json.JSONException;
  20. import org.json.JSONObject;
  21. import org.xmlpull.v1.XmlPullParserException;
  22. import java.io.IOException;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. /**
  26. * 首页
  27. * Created by cg on 2015/10/27.
  28. */
  29. public class IndexFragment extends Fragment {
  30. //定义信息等等控件
  31. private ProgressDialog myProgressDialog;
  32. private PullToRefreshListView pullrefresh_index_list;                       //定义信息列表
  33. private List<IndexList> list_index;                                         //定义显示数据的list
  34. private Index_lv_Adapter indexAdapter;                                      //定义Adapter
  35. @Override
  36. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  37. Bundle savedInstanceState) {
  38. View view = inflater.inflate(R.layout.fragment_index,container,false);
  39. initControls(view);
  40. return view;
  41. }
  42. /**
  43. * 对下拉列表控件进行初始化,并初始化进度控件
  44. * @param view
  45. */
  46. private void initControls(View view) {
  47. pullrefresh_index_list = (PullToRefreshListView)view.findViewById(R.id.pullrefresh_index_list);
  48. list_index = new ArrayList<>();
  49. //初始化数据
  50. initDatas();
  51. // 设置下拉和上拖监听事件
  52. pullrefresh_index_list
  53. .setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {
  54. @Override
  55. public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
  56. // 模拟加载任务
  57. new GetDownDataTask().execute();
  58. }
  59. @Override
  60. public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
  61. //Log.e("onPullUpToRefresh","有反应没有啊");
  62. new GetUpDataTask().execute();
  63. }
  64. });
  65. }
  66. /**
  67. * 初始时,加载10条数据上来
  68. */
  69. private void initDatas()
  70. {
  71. if(netUntils.isNetworkAvailable(getActivity())) {
  72. // 初始化数据和数据源
  73. myProgressDialog = new ProgressDialog(getActivity());
  74. myProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);  //设置风格为圆形进度条
  75. myProgressDialog.setTitle("提示");                                 //设置标题
  76. myProgressDialog.setMessage("数据加载中,请稍等...");                 //设置内容
  77. myProgressDialog.setIndeterminate(false);                         //设置进度是否为不明确
  78. myProgressDialog.setCancelable(true);                             //设置进度条是否可以按退回键取消
  79. myProgressDialog.show();
  80. new Thread(new Runnable() {
  81. @Override
  82. public void run() {
  83. Message msg = new Message();
  84. try {
  85. //得到数据
  86. String soapObject = webservicesUntils.getIndexItemList("", "", 1, 10);
  87. //判断如果数据返回的不是错误代码0,则对返回的json数据进行解析,将数据存入List中
  88. if (soapObject != "0") {
  89. try {
  90. JSONArray jsonArray = new JSONArray(soapObject);
  91. for (int i = 0; i < jsonArray.length(); i++) {
  92. JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
  93. IndexList comm = new IndexList();
  94. comm.setUserPic(jsonObject2.getString("userPic"));
  95. comm.setQuestionTitle(jsonObject2.getString("questionTitle"));
  96. comm.setQuestionSize(jsonObject2.getString("questionSize"));
  97. comm.setQuestionContent(jsonObject2.getString("questionContent"));
  98. comm.setQuestionID(jsonObject2.getInt("questionID"));
  99. list_index.add(comm);
  100. }
  101. } catch (JSONException e) {
  102. // TODO Auto-generated catch block
  103. e.printStackTrace();
  104. }
  105. }
  106. msg.arg1 = 1;
  107. handler.sendMessage(msg);
  108. } catch (Exception ex) {
  109. msg.arg1 = 2;
  110. }
  111. }
  112. }).start();
  113. }else
  114. {
  115. Toast.makeText(getActivity(), "请检查您的网络是否打开!", Toast.LENGTH_LONG).show();
  116. }
  117. }
  118. Handler handler = new Handler(){
  119. @Override
  120. public void handleMessage(Message msg) {
  121. if(msg.arg1==1)
  122. {
  123. if(list_index!=null)
  124. {
  125. //设置适配器
  126. indexAdapter = new Index_lv_Adapter(getActivity(),list_index);
  127. pullrefresh_index_list.setAdapter(indexAdapter);
  128. }else
  129. {
  130. Toast.makeText(getActivity(), "无数据加载!", Toast.LENGTH_LONG).show();
  131. }
  132. }else
  133. {
  134. Toast.makeText(getActivity(), "数据读取失败!", Toast.LENGTH_LONG).show();
  135. }
  136. myProgressDialog.dismiss();
  137. }
  138. };
  139. /**
  140. * 下拉时,更新数据,从list中提取第一条数据也就是最新的一条,传回,以供判断是否有新的数据,如果有,则对listView进行刷新
  141. * 通过return将得到的数据返回给protected void onPostExecute(String result),以便在前台显示
  142. */
  143. private class GetDownDataTask extends AsyncTask<Void, Void, String>
  144. {
  145. //异步取数据
  146. @Override
  147. protected String doInBackground(Void... params)
  148. {
  149. try
  150. {
  151. //这里调用一个webServices取新添加的数据
  152. //原理:取现在list中最新的数据,去后台数据中进行对比,如果有比这个新的数据,就取,没有则返回0
  153. String soapObject = webservicesUntils.getIndexItemList_refresh(String.valueOf(list_index.get(0).getQuestionID()));
  154. return soapObject;
  155. }  catch (XmlPullParserException e) {
  156. e.printStackTrace();
  157. } catch (IOException e) {
  158. e.printStackTrace();
  159. }
  160. return "" ;
  161. }
  162. //将数据显示在前台
  163. @Override
  164. protected void onPostExecute(String result)
  165. {
  166. if(!result.equals("0"))
  167. {
  168. try {
  169. //我们采用了.add(location,comm)方法,指定了插入的位置,这样就把新的数据直接插入到前面
  170. //list_index.clear();                //清空List<>中的数据
  171. JSONArray jsonArray = new JSONArray(result);
  172. for (int i = 0; i < jsonArray.length(); i++) {
  173. JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
  174. IndexList comm = new IndexList();
  175. comm.setUserPic(jsonObject2.getString("userPic"));
  176. comm.setQuestionTitle(jsonObject2.getString("questionTitle"));
  177. comm.setQuestionSize(jsonObject2.getString("questionSize"));
  178. comm.setQuestionContent(jsonObject2.getString("questionContent"));
  179. comm.setQuestionID(jsonObject2.getInt("questionID"));
  180. list_index.add(0,comm);
  181. }
  182. indexAdapter.notifyDataSetChanged();
  183. //num=1;
  184. } catch (JSONException e) {
  185. // TODO Auto-generated catch block
  186. e.printStackTrace();
  187. }
  188. }
  189. //刷新结束,必须加上此句,不然下面的加载图标一下在
  190. pullrefresh_index_list.onRefreshComplete();
  191. }
  192. }
  193. /**
  194. * 向上刷新加载更多的数据
  195. */
  196. public class GetUpDataTask extends AsyncTask<Void, Void, String> {
  197. @Override
  198. protected String doInBackground(Void... params) {
  199. try {
  200. String soapObject = webservicesUntils.getIndexItemList("", "", list_index.size() + 1, 10);
  201. return soapObject;
  202. } catch (Exception ex) {
  203. return "0";
  204. }
  205. }
  206. @Override
  207. protected void onPostExecute(String result) {
  208. if (result != "0") {
  209. try {
  210. JSONArray jsonArray = new JSONArray(result);
  211. for (int i = 0; i < jsonArray.length(); i++) {
  212. JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
  213. IndexList comm = new IndexList();
  214. comm.setUserPic(jsonObject2.getString("userPic"));
  215. comm.setQuestionTitle(jsonObject2.getString("questionTitle"));
  216. comm.setQuestionSize(jsonObject2.getString("questionSize"));
  217. comm.setQuestionContent(jsonObject2.getString("questionContent"));
  218. comm.setQuestionID(jsonObject2.getInt("questionID"));
  219. list_index.add(comm);
  220. }
  221. indexAdapter.notifyDataSetChanged();
  222. } catch (JSONException e) {
  223. // TODO Auto-generated catch block
  224. e.printStackTrace();
  225. }
  226. }
  227. //刷新结束,必须加上此句,不然下面的加载图标一下在
  228. pullrefresh_index_list.onRefreshComplete();
  229. }
  230. }
  231. }
  232. 显示的结果图:

在这里,要说明的一点是PullToRefreshListView控件的setOnRefreshListener方法, 它里面有两个实现方法, 一个是我们在程序中所使用的
new PullToRefreshBase.OnRefreshListener2<ListView>()方法, 这个是既有上拉,又有下拉的方法,还有一个是
new PullToRefreshBase.OnRefreshListener<ListView>()方法,这个是只有上拉
可通过http://blog.csdn.net/lmj623565791/article/details/38238749这个blog了解更细的使用说明

转自:http://blog.csdn.net/chenguang79/article/details/49508781

仿知乎程序(三)读取webService,解析json,volley以及PullToRefreshListView的使用相关推荐

  1. php 读取 js json格式数据,js读取和解析JSON数据的方法

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生格式,这意 ...

  2. 小程序另一种解析json

    emmmm这个网站真是会出难题 另一种解析json json数据如下 {"reason":"请求成功","result":{"li ...

  3. VUE仿知乎网站(三)首页主体部分开发

  4. 安卓案例:读取与解析JSON

    文章目录 一.运行效果 二.实现步骤 1.创建安卓应用ParseJson 2.切换到Project视图,在main

  5. 【猫项目】微信小程序 后端返回数据解析json

    例如:请求数据返回的是字符串{a:1,b:2,c=3} 返回的是没有转码的json数据格式,而且是字符串类型.这时候需要把之转换为对象,返回的数据有很多链接,直接用JSON.prase(string) ...

  6. cocos2d-x自代的Json库解析json(转)

    之前在2.0.3版本的时候用过一个jsonCpp的库,不过后来的版本是好像加入了json库,因为cocostudio导出的界面数据和骨格动画数据用的其实就是json文件.没有看库里边是怎么解析的,在网 ...

  7. java+解析未知json_在Java中解析JSON时如何忽略未知属性– Jackson @JsonIgnoreProperties注释示例...

    java+解析未知json 使用Jackson API在Java中解析JSON时的常见问题之一是,当您的JSON包含未知属性(即您的Java类没有对应于所有JSON属性的所有字段)时,该操作将失败. ...

  8. qt中解析json字符串的时候出现错误missingNameSeperator

    概述 当解析json字符串,编译代码的时候没有问题,但是当程序调式运行到解析json字符串的时候,即这句: QJsonParseError parseError;QJsonDocument doc = ...

  9. 大厂程序员接私活被坑, 还被放鸽子,那源码就开源-基于SSM仿知乎小程序

    最近很郁闷,一个女粉丝找我要开发一个系统.说是很着急.   但是费用不高,说自己没钱.   我平时事也很多,又不是很想接.   说了一大堆苦情的话,然后说自己的要求不高,没有ui要求,   我就接了. ...

最新文章

  1. 【机器学习算法-python实现】决策树-Decision tree(2) 决策树的实现
  2. 招聘│微软云计算英雄帖来了,快接招!
  3. 用javascript完成pos机的输入输出
  4. 远程连接linux的mysql_【Linux开启mysql远程连接的设置步骤】 mysql开启远程连接
  5. 华为在 5G 初期不考虑盈利;​网易发布数据中台;微软 SQL Server 2019 免费支持 Java | 极客头条...
  6. 解决“此图片来自微信公众平台未经允许不可引用”的方法
  7. 金三银四面试季—20道精选JVM重点面试问题!
  8. Knockout v3.4.0 中文版教程-6-计算监控-可写的计算监控
  9. c#面试3(选择题)
  10. Tuxedo中间件 配置维护记录
  11. 4. Python--Scipy库(上/1-6)
  12. 在cmd下载清华镜像
  13. 京东X无人超市布局瞄准加油站,下一个场景会在哪儿
  14. Android对应颜色值代码
  15. 你评论,我赠书~【TFS-CLUB社区 第11期赠书活动】〖Unity手机游戏开发:从搭建到发布上线全流程实战〗等你来拿,参与评论,即可有机获得
  16. 中国地质大学武汉大学计算机学院,董燕妮-地球物理与空间信息学院
  17. 2021-2027全球及中国红外探测器芯片行业研究及十四五规划分析报告
  18. win7 win8.1搜索不到隐藏中文wifi 已添加隐藏wifi但是没显示
  19. win32api之虚拟键盘
  20. APP性能测试--帧率测试

热门文章

  1. OKTA demo 推荐第一种
  2. Anaconda详细安装教程
  3. HTML5前端开发实战02-旅游网页面设计
  4. (2011-05-12 旧博文搬家)BOX2D_坦克大战
  5. NPOI使用手册[转]
  6. 130242014024-陈敏敏-第3次实验
  7. 数据中台选型必读(三):什么企业适合上数据中台?
  8. CodeWarrior v11.1初体验
  9. Dreamweaver
  10. 另眼相看“那些争议最大的编程观点”