首页 > 移动开发 > Android仿人人客户端——新鲜事之完整篇

Android仿人人客户端——新鲜事之完整篇

声明:仿人人项目,所用所有图片资源都来源于其它Android移动应用,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片。

 

有关新鲜事模块的实现前面已聊过一部分,这篇在前面Android仿人人客户端(v5.7.1)——新鲜事之状态这篇的基础上,将剩下部分的实现和在实现过程中代码的调整一一详细的聊聊。

一、基于开源组件XListView实现下拉刷新和向上滚动或点击加载更多。

1、在布局文件(fresh_news.xml)中加入XListView组件,如下

 

[html][/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="fill_parent"
  4.     android:layout_height="fill_parent"
  5.     android:background="#FFFFFF"
  6.     android:orientation="vertical" >
  7.     <com.everyone.android.widget.TopMenuNavbar
  8.         android:id="@+id/rl_top_menu_navbar"
  9.         style="@style/top_navbar" />
  10.     <include
  11.         android:id="@+id/loading"
  12.         layout="@layout/loading_progressbar" />
  13.     <com.everyone.android.widget.XListView
  14.         android:id="@+id/listview"
  15.         android:layout_width="fill_parent"
  16.         android:layout_height="wrap_content"
  17.         android:background="#00000000"
  18.         android:cacheColorHint="#00000000"
  19.         android:divider="@drawable/v5_0_1_newsfeed_divider"
  20.         android:listSelector="@null"
  21.         android:fastScrollEnabled="true"
  22.        />
  23. </LinearLayout>

 

2、在新鲜事视图中做ListView组件替换,让新鲜事视图(FreshNewsLayout)类实现IXListViewListener接口,代码如下:

 

[java][/java] view plaincopy

  1. public class FreshNewsLayout extends FrameLayout implements IXListViewListener, OnClickListener {}

你会发现新鲜事视图(FreshNewsLayout)类中会多如下两个方法:

[java][/java] view plaincopy

  1. // 下拉刷新
  2. @Override
  3. public void onRefresh() {
  4. }
  5. // 加载更多
  6. @Override
  7. public void onLoadMore() {
  8. }

用XListView替换掉原生的ListView组件,并绑定数据适配器和设置事件监听器。具体代码如下:

 

[java][/java] view plaincopy

  1. mListView = (XListView) freshNewsViewRoot.findViewById(R.id.listview);
  2. mListView.setPullLoadEnable(false);
  3. mListView.setPullRefreshEnable(false);
  4. mListView.setXListViewListener(this);
  5. mFreshNewsAdapter = new FreshNewsAdapter(mActivity, mFreshNewsList);
  6. mListView.setAdapter(mFreshNewsAdapter);

3、其它的代码不变,运行程序,效果图如下:

 

点击顶部左侧的menu按钮,效果图如下:

 

4、添加下拉刷新和向上滚动加载更多,代码如下:

 

[java][/java] view plaincopy

  1. // 下拉刷新
  2.  @Override
  3.  public void onRefresh() {
  4.      page = 1;
  5.      getFreshNews();
  6.  }
  7.  // 加载更多
  8.  @Override
  9.  public void onLoadMore() {
  10.      page++;
  11.      getFreshNews();
  12.  }

下拉刷新,运行效果图如下:

 

 

 

向上滑动加载更多运行,效果图如下:

 

 

二、选择顶部下拉列表中的Item,对新鲜事进行过滤处理。

1、再次罗列人人官方API 里提供有关新鲜事类型的一系列数字和各个数字含义见下面:

10 更新状态的新鲜事;11 page更新状态的新鲜事; 20 发表日志的新鲜事;21 分享日志的新鲜事;22 page发表日志的新鲜事;

23 page分享日志的新鲜事;30 上传照片的新鲜事;31 page上传照片的新鲜事;32 分享照片的新鲜事;33 分享相册的新鲜事;

34 修改头像的新鲜事;35 page修改头像的新鲜事; 36 page分享照片的新鲜事;40 成为好友的新鲜事;41 成为page粉丝的新鲜事;

50 分享视频的新鲜事;51 分享链接的新鲜事; 52 分享音乐的新鲜事; 53 page分享视频的新鲜事;54 page分享链接的新鲜事;

55 page分享音乐的新鲜事。

对新鲜事类型进行分类,具体代码如下:

 

[java][/java] view plaincopy

  1. /**
  2.   * 发表的新鲜事,默认请求所有类型的新鲜事
  3.   */
  4.  private static final String FRESH_NEWS_TYPE_ALL = "10,11,20,21,22,23,30,31,32,33,34,35,36";
  5.  /**
  6.   * 好友内容
  7.   */
  8.  private static final String FRESH_NEWS_TYPE_FRIEND = "40";
  9.  /**
  10.   * 特别关注
  11.   */
  12.  private static final String FRESH_NEWS_TYPE_FOCUS = null;
  13.  /**
  14.   * 状态
  15.   */
  16.  private static final String FRESH_NEWS_TYPE_STATUS = "10,11";
  17.  /**
  18.   * 照片
  19.   */
  20.  private static final String FRESH_NEWS_TYPE_PHOTO = "30,31";
  21.  /**
  22.   * 位置
  23.   */
  24.  private static final String FRESH_NEWS_TYPE_PLACE = null;
  25.  /**
  26.   * 分享的新鲜事
  27.   */
  28.  private static final String FRESH_NEWS_TYPE_SHARE = "21,23,32,33,36";
  29.  /**
  30.   * 日志
  31.   */
  32.  private static final String FRESH_NEWS_TYPE_BLOG = "20,22";

 注:人人的官方API里没有提供相关的数字表示特别关注和位置,故我目前暂时给赋值为null。有关音频和视屏的部分暂时未去实现。

 

2、将新鲜事的分类与顶部下拉列表进行关联。

a.将新鲜事类型放入一个数组中,代码如下:

 

[java][/java] view plaincopy

  1. /**
  2.     * 新鲜事类型数组
  3.     */
  4.    private String[] freshNewsTypes = {FRESH_NEWS_TYPE_ALL, FRESH_NEWS_TYPE_FRIEND,
  5.            FRESH_NEWS_TYPE_FOCUS, FRESH_NEWS_TYPE_STATUS,FRESH_NEWS_TYPE_PHOTO,
  6.            FRESH_NEWS_TYPE_PLACE, FRESH_NEWS_TYPE_SHARE,FRESH_NEWS_TYPE_BLOG};

 

b.设置默认的新鲜事类型

 

[java][/java] view plaincopy

  1. /**
  2.      * 新鲜事类型,默认为当前所支持的全部类型
  3.      */
  4.     private String fresh_news_type = FRESH_NEWS_TYPE_ALL;

 

c.顶部下拉列表Item单击事件的处理,代码如下:

 

[java][/java] view plaincopy

  1. mPopupListView.setOnItemClickListener(new OnItemClickListener() {
  2.             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  3.                 mPopupWindow.dismiss();
  4.                 // 当前选择的项与之前的一样,则不做处理。
  5.                 if (mPopupAdapter.getPosition() == position) {
  6.                     return;
  7.                 }
  8.                 // 新鲜事过滤事件处理
  9.                 fresh_news_type = freshNewsTypes[position];
  10.                 LogUtil.i(TAG, "onItemClick position = " + position);
  11.                 LogUtil.i(TAG, "onItemClick fresh_news_type = " + fresh_news_type);
  12.                 if(fresh_news_type == null){
  13.                     Toast.makeText(mActivity.getApplicationContext(), "抱歉,您选择的项官方API暂时未提供如何获取相应的数据!", Toast.LENGTH_LONG).show();
  14.                     return;
  15.                 }
  16.                 mPopupAdapter.setPosition(position);
  17.                 mPopupAdapter.notifyDataSetChanged();
  18.                 topMenuNavbar.tvTitle.setText(mTexts[position]);
  19.                 page = 1;
  20.                 mFreshNewsList.clear();
  21.                 getFreshNews();
  22.             }
  23.         });

 

         d. 向服务器端发送请求的getFreshNews()方法里面的具体处理,代码如下:

 

 

[java][/java] view plaincopy

  1. /**
  2.   * 向服务器端请求新鲜事的数据
  3.   */
  4.  public void getFreshNews() {
  5.      String accessToken = mAuthTokenManager.getAccessToken();
  6.      LogUtil.e(TAG, "accessToken = " + accessToken);
  7.      Map<String, String> parameter = new HashMap<String, String>();
  8.      parameter.put("v", "1.0"); // API的版本号,固定值为1.0
  9.      parameter.put("access_token", accessToken); // OAuth2.0验证授权后获得的token。
  10.      parameter.put("format", "JSON"); // 返回值的格式。请指定为JSON或者XML
  11.      parameter.put("call_id", "1.0"); // 请求队列号
  12.      parameter.put("method", "feed.get");
  13.      parameter.put("type", fresh_news_type); // 新鲜事的类别,多个类型以逗号分隔,type列表
  14.      // parameter.put("uid", ""); // 支持传入当前用户的一个好友ID,表示获取此好友的新鲜事,如果不传,默认为获取当前用户的新鲜事
  15.      parameter.put("page", page + ""); // 支持分页,指定页号,页号从1开始,默认值为1
  16.      parameter.put("count", pageCount + ""); // 支持分页,每一页记录数,默认值为30,最大50
  17.      AsyncHttpsPost asyncHttpsPost = new AsyncHttpsPost(Constant.API_SERVER_URL, parameter, new ParseCallback() {
  18.          @Override
  19.          public LinkedList<FreshNews> parse(String json) throws JSONException {
  20.              LogUtil.i(TAG, "json = " + json);
  21.              if ("[]".equals(json)) {
  22.                  return null;
  23.              }
  24.              Gson gson = new Gson();
  25.              java.lang.reflect.Type type = new TypeToken<LinkedList<FreshNews>>() {
  26.              }.getType();
  27.              LinkedList<FreshNews> freshNewsList = gson.fromJson(json, type);
  28.              LogUtil.e(TAG, "freshNewsList = " + freshNewsList.size());
  29.              return freshNewsList;
  30.          }
  31.      }, new ResultCallback() {
  32.          @Override
  33.          public void onSuccess(final Object obj) {
  34.              mHandler.post(new Runnable() {
  35.                  @Override
  36.                  public void run() {
  37.                      if (obj != null && obj instanceof LinkedList) {
  38.                          @SuppressWarnings("unchecked")
  39.                          LinkedList<FreshNews> freshNewsList = (LinkedList<FreshNews>) obj;
  40.                          if (freshNewsList.size() > 0) {
  41.                              // 下拉刷新的数据去重复处理
  42.                              if (page == 1 && mFreshNewsList.size() > 0) {
  43.                                  for (FreshNews freshNews : freshNewsList) {
  44.                                      boolean flage = false;
  45.                                      for (FreshNews fresh : mFreshNewsList) {
  46.                                          if(freshNews.getPost_id() == fresh.getPost_id()){
  47.                                              flage = true;
  48.                                          }
  49.                                      }
  50.                                      if(flage == false){
  51.                                          mFreshNewsList.addFirst(freshNews);
  52.                                      }
  53.                                  }
  54.                              } else {
  55.                                  mFreshNewsList.addAll(freshNewsList);
  56.                              }
  57.                              mListView.setPullLoadEnable(true);
  58.                              mListView.setPullRefreshEnable(true);
  59.                          }
  60.                      } else {
  61.                          mListView.setPullLoadEnable(false);
  62.                      }
  63.                      if (page == 1) {
  64.                          if (mLoadingView.isShown()) {
  65.                              mLoadingView.setVisibility(View.GONE);
  66.                          }
  67.                          mFreshNewsAdapter.notifyDataSetInvalidated();
  68.                          mListView.stopRefresh();
  69.                      } else {
  70.                          mFreshNewsAdapter.notifyDataSetChanged();
  71.                          mListView.stopLoadMore();
  72.                      }
  73.                      // 设置刷新时间
  74.                      String refreshTime = mDateFormat.format(System.currentTimeMillis());
  75.                      mListView.setRefreshTime(refreshTime);
  76.                  }
  77.              });
  78.          }
  79.          @Override
  80.          public void onFail(int errorCode) {
  81.              LogUtil.i(TAG, "freshNewsList errorCode = " + errorCode);
  82.          }
  83.      });
  84.      mDefaultThreadPool.execute(asyncHttpsPost);
  85.      mAsyncRequests.add(asyncHttpsPost);
  86.  }

先看下运行后的效果图,按状态过滤,运行效果图如下:

 

 

按照片过滤,运行效果图如下:

 

按分享过滤,运行效果图如下:

 

按日志过滤,运行效果图如下:

 

e.看完效果图,我们来看看ListView的Item布局文件(fresh_news_list_item.xml),配置内容如下:

 

[html][/html] view plaincopy

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="wrap_content"
  5.     android:background="@drawable/fresh_news_list_item_selector" >
  6.     <!-- 头像 -->
  7.     <ImageView
  8.         android:id="@+id/iv_user_image"
  9.         android:layout_width="43.0dip"
  10.         android:layout_height="43.0dip"
  11.         android:layout_marginLeft="10.0dip"
  12.         android:layout_marginTop="8.0dip"
  13.         android:saveEnabled="true"
  14.         android:scaleType="center"
  15.         android:src="@drawable/v5_0_1_widget_default_head" />
  16.     <LinearLayout
  17.         android:layout_width="fill_parent"
  18.         android:layout_height="wrap_content"
  19.         android:layout_marginLeft="8dip"
  20.         android:layout_marginRight="8dip"
  21.         android:layout_marginTop="8dip"
  22.         android:layout_toRightOf="@+id/iv_user_image"
  23.         android:orientation="vertical"
  24.         android:paddingBottom="8dip" >
  25.         <!-- 昵称 -->
  26.         <TextView
  27.             android:id="@+id/tv_nickname"
  28.             android:layout_width="wrap_content"
  29.             android:layout_height="wrap_content"
  30.             android:layout_marginBottom="5.0dip"
  31.             android:textColor="#ff005092"
  32.             android:textSize="16sp" />
  33.         <!-- 用户自定义输入的内容 -->
  34.         <TextView
  35.             android:id="@+id/tv_message_content"
  36.             android:layout_width="fill_parent"
  37.             android:layout_height="wrap_content"
  38.             android:layout_marginBottom="5.0dip"
  39.             android:textColor="#000000"
  40.             android:textSize="15.0sp" />
  41.         <!-- 状态 -->
  42.         <include
  43.             android:id="@+id/ll_status"
  44.             layout="@layout/fresh_news_item_state"
  45.             android:visibility="gone" />
  46.         <!-- 图片 -->
  47.         <include
  48.             android:id="@+id/ll_photo"
  49.             layout="@layout/fresh_news_item_photo"
  50.             android:visibility="gone" />
  51.         <!-- 日志 -->
  52.         <include
  53.             android:id="@+id/ll_blog"
  54.             layout="@layout/fresh_news_item_blog"
  55.             android:visibility="gone" />
  56.         <!-- 更新头像 -->
  57.         <ImageView
  58.             android:id="@+id/iv_update_icon"
  59.             android:layout_width="80dip"
  60.             android:layout_height="80dip"
  61.             android:scaleType="centerCrop"
  62.             android:visibility="gone" />
  63.         <!-- 时间和来源 -->
  64.         <RelativeLayout
  65.             android:layout_width="fill_parent"
  66.             android:layout_height="wrap_content" >
  67.             <!-- 时间 -->
  68.             <TextView
  69.                 android:id="@+id/tv_published"
  70.                 android:layout_width="wrap_content"
  71.                 android:layout_height="wrap_content"
  72.                 android:layout_marginTop="8.0dip"
  73.                 android:drawablePadding="3dip"
  74.                 android:textColor="#ff666666"
  75.                 android:textSize="12.0sp" />
  76.             <!-- 来源 -->
  77.             <TextView
  78.                 android:id="@+id/tv_source"
  79.                 android:layout_width="wrap_content"
  80.                 android:layout_height="wrap_content"
  81.                 android:layout_marginLeft="15dip"
  82.                 android:layout_marginTop="8.0dip"
  83.                 android:layout_toRightOf="@+id/tv_published"
  84.                 android:textColor="#ff666666"
  85.                 android:textSize="12.0sp" />
  86.         </RelativeLayout>
  87.         <!-- 评论信息 -->
  88.         <LinearLayout
  89.             android:id="@+id/ll_comments_content"
  90.             android:layout_width="fill_parent"
  91.             android:layout_height="wrap_content"
  92.             android:layout_marginTop="7.0dip"
  93.             android:background="@drawable/fresh_news_popup"
  94.             android:orientation="vertical"
  95.             android:padding="10dip"
  96.             android:visibility="gone" />
  97.     </LinearLayout>
  98. </RelativeLayout>

其中包含的有关状态的布局文件(fresh_news_item_state.xml),内容如下:

 

 

[html][/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="fill_parent"
  4.     android:layout_height="wrap_content"
  5.     android:orientation="horizontal" >
  6.     <View
  7.         android:layout_width="2dip"
  8.         android:layout_height="fill_parent"
  9.         android:background="#20333333" />
  10.     <LinearLayout
  11.         android:layout_width="fill_parent"
  12.         android:layout_height="wrap_content"
  13.         android:layout_marginLeft="10dip"
  14.         android:orientation="vertical" >
  15.         <TextView
  16.             android:id="@+id/tv_status_name"
  17.             android:layout_width="wrap_content"
  18.             android:layout_height="wrap_content"
  19.             android:textColor="#ff005092"
  20.             android:textSize="14sp" />
  21.         <TextView
  22.             android:id="@+id/tv_status_content"
  23.             android:layout_width="wrap_content"
  24.             android:layout_height="wrap_content"
  25.             android:layout_marginTop="8dip"
  26.             android:textColor="#ff888888"
  27.             android:textSize="14sp" />
  28.     </LinearLayout>
  29. </LinearLayout>

其中包含的有关照片的布局文件(fresh_news_item_photo.xml),内容如下:

[html][/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="fill_parent"
  4.     android:layout_height="wrap_content"
  5.     android:orientation="horizontal" >
  6.     <View
  7.         android:id="@+id/v_photo_left_line"
  8.         android:layout_width="2dip"
  9.         android:layout_height="fill_parent"
  10.         android:layout_marginRight="10dip"
  11.         android:background="#20333333" />
  12.     <LinearLayout
  13.         android:layout_width="fill_parent"
  14.         android:layout_height="wrap_content"
  15.         android:orientation="vertical" >
  16.         <TextView
  17.             android:id="@+id/tv_photo_owner_name"
  18.             android:layout_width="wrap_content"
  19.             android:layout_height="wrap_content"
  20.             android:textColor="#ff005092"
  21.             android:textSize="14sp" />
  22.         <TextView
  23.             android:id="@+id/tv_photo_describe"
  24.             android:layout_width="wrap_content"
  25.             android:layout_height="wrap_content"
  26.             android:layout_marginTop="10dip"
  27.             android:textColor="#000000"
  28.             android:textSize="13sp" />
  29.         <ImageView
  30.             android:id="@+id/iv_photo_image"
  31.             android:layout_width="wrap_content"
  32.             android:layout_height="wrap_content"
  33.             android:layout_marginTop="10dip" />
  34.        <!--  人人官方的做法,显示固定大小的图片,并对原图进行剪裁。根据设置的宽高选择适中的区域进行裁剪-->
  35.         <!--
  36.                 <ImageView
  37.                     android:id="@+id/iv_photo_image"
  38.                     android:layout_width="150dip"
  39.                     android:layout_height="150dip"
  40.                     android:layout_marginTop="10dip"
  41.                     android:scaleType="centerCrop" />
  42.         -->
  43.         <TextView
  44.             android:id="@+id/tv_photo_source"
  45.             android:layout_width="wrap_content"
  46.             android:layout_height="wrap_content"
  47.             android:layout_marginTop="10dip"
  48.             android:textColor="#ff888888"
  49.             android:textSize="13sp" />
  50.     </LinearLayout>
  51. </LinearLayout>

其中包含的有关日志的布局文件(fresh_news_item_blog.xml),内容如下:

[html][/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="fill_parent"
  4.     android:layout_height="wrap_content"
  5.     android:orientation="horizontal" >
  6.     <View
  7.         android:id="@+id/v_blog_left_line"
  8.         android:layout_width="2dip"
  9.         android:layout_height="fill_parent"
  10.         android:layout_marginRight="10dip"
  11.         android:background="#20333333" />
  12.     <LinearLayout
  13.         android:layout_width="fill_parent"
  14.         android:layout_height="wrap_content"
  15.         android:orientation="vertical" >
  16.         <TextView
  17.             android:id="@+id/tv_blog_owner_name"
  18.             android:layout_width="wrap_content"
  19.             android:layout_height="wrap_content"
  20.             android:textColor="#ff005092"
  21.             android:textSize="14sp" />
  22.         <TextView
  23.             android:id="@+id/tv_blog_title"
  24.             android:layout_width="wrap_content"
  25.             android:layout_height="wrap_content"
  26.             android:layout_marginBottom="8dip"
  27.             android:layout_marginTop="8dip"
  28.             android:textColor="#ff005092"
  29.             android:textSize="14sp" />
  30.         <TextView
  31.             android:id="@+id/tv_blog_describe"
  32.             android:layout_width="wrap_content"
  33.             android:layout_height="wrap_content"
  34.             android:textColor="#ff888888"
  35.             android:textSize="14sp" />
  36.     </LinearLayout>
  37. </LinearLayout>

 

三、完整代码

1、组件XListView的数据适配器(FreshNewsAdapter)的源码如下:

[java][/java] view plaincopy

  1. package com.everyone.android.ui.freshnews;
  2. import java.util.LinkedList;
  3. import android.graphics.Color;
  4. import android.text.TextUtils;
  5. import android.util.TypedValue;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.view.ViewGroup.LayoutParams;
  10. import android.widget.BaseAdapter;
  11. import android.widget.ImageView;
  12. import android.widget.LinearLayout;
  13. import android.widget.TextView;
  14. import com.everyone.android.R;
  15. import com.everyone.android.bitmap.ImageLoader;
  16. import com.everyone.android.entity.Attachment;
  17. import com.everyone.android.entity.Comment;
  18. import com.everyone.android.entity.Comments;
  19. import com.everyone.android.entity.FreshNews;
  20. import com.everyone.android.entity.ImageInfo;
  21. import com.everyone.android.entity.Source;
  22. import com.everyone.android.ui.EveryoneActivity;
  23. import com.everyone.android.utils.DensityUtil;
  24. import com.everyone.android.utils.LogUtil;
  25. /**
  26.  * 功能描述:新鲜事列表数据适配器
  27.  * @author android_ls
  28.  */
  29. public class FreshNewsAdapter extends BaseAdapter {
  30.     /**
  31.      * LOG打印标签
  32.      */
  33.     private static final String TAG = "FreshNewsAdapter";
  34.     private LayoutInflater inflater;
  35.     private LinkedList<FreshNews> mFreshNewsList;
  36.     private EveryoneActivity mActivity;
  37.     private ImageLoader mImageLoader;
  38.     public FreshNewsAdapter(EveryoneActivity activity, LinkedList<FreshNews> freshNewsList) {
  39.         inflater = LayoutInflater.from(activity);
  40.         mActivity = activity;
  41.         mFreshNewsList = freshNewsList;
  42.         this.mImageLoader = new ImageLoader(mActivity);
  43.     }
  44.     @Override
  45.     public int getCount() {
  46.         return mFreshNewsList.size();
  47.     }
  48.     @Override
  49.     public Object getItem(int arg0) {
  50.         return mFreshNewsList.get(arg0);
  51.     }
  52.     @Override
  53.     public long getItemId(int position) {
  54.         return position;
  55.     }
  56.     /* (non-Javadoc)
  57.      * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
  58.      */
  59.     @Override
  60.     public View getView(final int position, View convertView, ViewGroup parent) {
  61.         ViewHolder holder = null;
  62.         if (convertView == null) {
  63.             convertView = inflater.inflate(R.layout.fresh_news_list_item, null);
  64.             holder = new ViewHolder();
  65.             holder.imageView1 = (ImageView) convertView.findViewById(R.id.iv_user_image);
  66.             holder.text1 = (TextView) convertView.findViewById(R.id.tv_nickname);
  67.             holder.text2 = (TextView) convertView.findViewById(R.id.tv_message_content);
  68.             holder.linearLayout1 = (LinearLayout) convertView.findViewById(R.id.ll_comments_content);
  69.             holder.linearLayout2 = (LinearLayout) convertView.findViewById(R.id.ll_status);
  70.             holder.linearLayout3 = (LinearLayout) convertView.findViewById(R.id.ll_photo);
  71.             holder.linearLayout4 = (LinearLayout) convertView.findViewById(R.id.ll_blog);
  72.             holder.text7 = (TextView) convertView.findViewById(R.id.tv_photo_owner_name);
  73.             holder.text8 = (TextView) convertView.findViewById(R.id.tv_photo_describe);
  74.             holder.imageView2 = (ImageView) convertView.findViewById(R.id.iv_photo_image);
  75.             holder.text9 = (TextView) convertView.findViewById(R.id.tv_photo_source);
  76.             holder.text10 = (TextView) convertView.findViewById(R.id.tv_blog_owner_name);
  77.             holder.text11 = (TextView) convertView.findViewById(R.id.tv_blog_title);
  78.             holder.text12 = (TextView) convertView.findViewById(R.id.tv_blog_describe);
  79.             holder.imageView3 = (ImageView) convertView.findViewById(R.id.iv_update_icon);
  80.             holder.text3 = (TextView) convertView.findViewById(R.id.tv_published);
  81.             holder.text4 = (TextView) convertView.findViewById(R.id.tv_source);
  82.             holder.text5 = (TextView) convertView.findViewById(R.id.tv_status_name);
  83.             holder.text6 = (TextView) convertView.findViewById(R.id.tv_status_content);
  84.             convertView.setTag(holder);
  85.         } else {
  86.             holder = (ViewHolder) convertView.getTag();
  87.         }
  88.         final FreshNews freshNews = mFreshNewsList.get(position);
  89.         // 姓名
  90.         holder.text1.setText(freshNews.getName());
  91.         LogUtil.i(TAG, "freshNews.getName() = " + freshNews.getName());
  92.         LogUtil.i(TAG, "description = " + freshNews.getDescription());
  93.         LogUtil.i(TAG, "freshNews.getMessage() = " + freshNews.getMessage());
  94.         LogUtil.i(TAG, "freshNews.getTitle() = " + freshNews.getTitle());
  95.         // 加载图像
  96.         String headurl = freshNews.getHeadurl();
  97.         LogUtil.i(TAG, "headurl = " + headurl);
  98.         if (!TextUtils.isEmpty(headurl)) {
  99.             int widthPx = DensityUtil.dip2px(mActivity, 43);
  100.             ImageInfo imgInfo = new ImageInfo(holder.imageView1, headurl, widthPx, widthPx);
  101.             mImageLoader.displayImage(imgInfo);
  102.         }
  103.         // 用户自定义输入的内容
  104.         String message = freshNews.getMessage();
  105.         if (!TextUtils.isEmpty(message)) {
  106.             holder.text2.setVisibility(View.VISIBLE);
  107.             holder.text2.setText(message);
  108.         } else {
  109.             holder.text2.setVisibility(View.GONE);
  110.         }
  111.         // 内容的前缀
  112.         String prefix = freshNews.getPrefix();
  113.         LogUtil.i(TAG, "freshNews.getPrefix() = " + prefix);
  114.         holder.linearLayout2.setVisibility(View.GONE);
  115.         holder.linearLayout3.setVisibility(View.GONE);
  116.         holder.linearLayout4.setVisibility(View.GONE);
  117.         holder.imageView3.setVisibility(View.GONE);
  118.         // 新鲜事中包含的媒体内容
  119.         LinkedList<Attachment> attachments = freshNews.getAttachment();
  120.         if (attachments != null) {
  121.             int size = attachments.size();
  122.             LogUtil.i(TAG, "size = " + size);
  123.             for (int i = 0; i < size; i++) {
  124.                 Attachment att = attachments.get(i);
  125.                 String media_type = att.getMedia_type();
  126.                 LogUtil.i(TAG, "media_type = " + media_type);
  127.                 LogUtil.i(TAG, "att.getContent() = " + att.getContent());
  128.                 LogUtil.i(TAG, "getHref = " + att.getHref());
  129.                 LogUtil.i(TAG, "att.getOwner_id() = " + att.getOwner_id());
  130.                 LogUtil.i(TAG, "getOwner_name() = " + att.getOwner_name());
  131.                 LogUtil.i(TAG, "getRaw_src() = " + att.getRaw_src());
  132.                 LogUtil.i(TAG, "getScr() = " + att.getScr());
  133.                 if ("status".equals(media_type)) {
  134.                     holder.linearLayout2.setVisibility(View.VISIBLE);
  135.                     holder.text5.setText(att.getOwner_name());
  136.                     holder.text6.setText(att.getContent());
  137.                 } else if ("photo".equals(media_type)) {
  138.                     holder.linearLayout3.setVisibility(View.VISIBLE);
  139.                     holder.imageView2.setImageBitmap(null);
  140.                     String raw_src = att.getRaw_src();
  141.                     if(raw_src != null){
  142.                         ImageInfo imgInfo = new ImageInfo(holder.imageView2, raw_src);
  143.                         mImageLoader.displayImage(imgInfo);
  144.                     }
  145.                     String owner_name = att.getOwner_name();
  146.                     if(!TextUtils.isEmpty(owner_name)){
  147.                         holder.text7.setVisibility(View.VISIBLE);
  148.                         holder.text7.setText(owner_name);
  149.                     } else {
  150.                         holder.text7.setVisibility(View.GONE);
  151.                     }
  152.                     String description = freshNews.getDescription();
  153.                     if(!TextUtils.isEmpty(description)){
  154.                         holder.text8.setVisibility(View.VISIBLE);
  155.                         holder.text8.setText(description);
  156.                     } else {
  157.                         holder.text8.setVisibility(View.GONE);
  158.                     }
  159.                     holder.text9.setText("【" + freshNews.getTitle() + "】");
  160.                 }else if ("blog".equals(media_type)) {
  161.                     holder.linearLayout4.setVisibility(View.VISIBLE);
  162.                     holder.text10.setText(att.getOwner_name());
  163.                     holder.text11.setText(freshNews.getTitle());
  164.                     holder.text12.setText(freshNews.getDescription());
  165.                 }else if ("link".equals(media_type)) {
  166.                 } else if ("album".equals(media_type)) {
  167.                 } else if ("link".equals(media_type)) {
  168.                 } else if ("video".equals(media_type)) {
  169.                 } else if ("audio".equals(media_type)) {
  170.                 }
  171.             }
  172.         }
  173.         // page代表公共主页新鲜事
  174.         int feedType = freshNews.getFeed_type();
  175.         LogUtil.i(TAG, "feedType = " + feedType);
  176.         switch (feedType) {
  177.         case 10: // 更新状态的新鲜事。
  178.         case 11: // page更新状态的新鲜事。
  179.             // 设置状态标识图标
  180.             holder.text3.setCompoundDrawablesWithIntrinsicBounds(R.drawable.v5_0_1_newsfeed_status_icon, 0, 0, 0);
  181.             break;
  182.         case 20: // 发表日志的新鲜事。
  183.         case 22: // page发表日志的新鲜事。
  184.             holder.text3.setCompoundDrawablesWithIntrinsicBounds(R.drawable.v5_0_1_newsfeed_blog_icon, 0, 0, 0);
  185.             holder.linearLayout4.setVisibility(View.VISIBLE);
  186.             holder.linearLayout4.findViewById(R.id.v_blog_left_line).setVisibility(View.GONE);
  187.             holder.text10.setVisibility(View.GONE);
  188.             if (!TextUtils.isEmpty(prefix)) {
  189.                 holder.text2.setVisibility(View.VISIBLE);
  190.                 holder.text2.setText(prefix);
  191.             } else {
  192.                 holder.text2.setVisibility(View.GONE);
  193.             }
  194.             holder.text11.setText(freshNews.getTitle());
  195.             holder.text12.setText(freshNews.getDescription());
  196.             break;
  197.         case 30: // 上传照片的新鲜事。
  198.         case 31: // page上传照片的新鲜事。
  199.             holder.text3.setCompoundDrawablesWithIntrinsicBounds(R.drawable.v5_0_1_newsfeed_photo_icon, 0, 0, 0);
  200.             holder.linearLayout3.findViewById(R.id.v_photo_left_line).setVisibility(View.GONE);
  201.             break;
  202.         case 21: // 分享日志的新鲜事。
  203.         case 23: // page分享日志的新鲜事。
  204.         case 32: // 分享照片的新鲜事。
  205.         case 33: // 分享相册的新鲜事。
  206.             // 设置分享标识图标
  207.             holder.text3.setCompoundDrawablesWithIntrinsicBounds(R.drawable.v5_0_1_newsfeed_share_icon, 0, 0, 0);
  208.             if(feedType == 32 || feedType == 33){
  209.                 holder.linearLayout3.findViewById(R.id.v_photo_left_line).setVisibility(View.VISIBLE);
  210.             }
  211.             break;
  212.         case 34: // 修改头像的新鲜事。
  213.         case 35: // page修改头像的新鲜事。
  214.             holder.text2.setVisibility(View.VISIBLE);
  215.             holder.text2.setText("更新头像");
  216.             holder.imageView3.setVisibility(View.VISIBLE);
  217.             ImageInfo imgInfo = new ImageInfo(holder.imageView3, headurl);
  218.             mImageLoader.displayImage(imgInfo);
  219.             break;
  220.         // ...
  221.         default:
  222.             break;
  223.         }
  224.         // 动态生成显示评论信息的Item
  225.         Comments comments = freshNews.getComments();
  226.         if (comments != null) {
  227.             LinkedList<Comment> commentList = comments.getComment();
  228.             if (commentList != null) {
  229.                 holder.linearLayout1.setVisibility(View.VISIBLE);
  230.                 if (holder.linearLayout1.getChildCount() > 0) {
  231.                     holder.linearLayout1.removeAllViews();
  232.                 }
  233.                 int count = comments.getCount();
  234.                 if (count > 0) {
  235.                     TextView tvCount = new TextView(mActivity);
  236.                     tvCount.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  237.                     tvCount.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
  238.                     tvCount.setSingleLine();
  239.                     tvCount.setCompoundDrawablePadding(5);
  240.                     tvCount.setPadding(0, 10, 0, 0);
  241.                     tvCount.setText(count + "条评论");
  242.                     tvCount.setTextColor(Color.parseColor("#ff005092"));
  243.                     tvCount.setCompoundDrawablesWithIntrinsicBounds(R.drawable.fresh_news_comment_icon, 0, 0, 0);
  244.                     holder.linearLayout1.addView(tvCount);
  245.                 }
  246.                 int size = commentList.size();
  247.                 LogUtil.i(TAG, "commentList size = " + size);
  248.                 for (int i = 0; i < size; i++) {
  249.                     Comment comment = commentList.get(i);
  250.                     LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  251.                     TextView tvContent = new TextView(mActivity);
  252.                     tvContent.setLayoutParams(layoutParams);
  253.                     tvContent.setTextColor(Color.BLACK);
  254.                     tvContent.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
  255.                     tvContent.setSingleLine();
  256.                     tvContent.setPadding(0, 10, 0, 0);
  257.                     tvContent.setText(comment.getName() + ":" + comment.getText());
  258.                     holder.linearLayout1.addView(tvContent);
  259.                     TextView tvTime = new TextView(mActivity);
  260.                     tvTime.setTextColor(Color.GRAY);
  261.                     tvTime.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
  262.                     tvTime.setLayoutParams(layoutParams);
  263.                     tvContent.setPadding(0, 5, 0, 10);
  264.                     tvTime.setText(comment.getTime());
  265.                     holder.linearLayout1.addView(tvTime);
  266.                 }
  267.             } else {
  268.                 holder.linearLayout1.setVisibility(View.GONE);
  269.             }
  270.         } else {
  271.             holder.linearLayout1.setVisibility(View.GONE);
  272.         }
  273.         // 对获取的时间字符串的处理
  274.         String updateTime = freshNews.getUpdate_time();
  275.         if (!TextUtils.isEmpty(updateTime)) {
  276.             updateTime = updateTime.substring(updateTime.indexOf("-") + 1, updateTime.lastIndexOf(":"));
  277.             updateTime = updateTime.replace("-", "月");
  278.             updateTime = updateTime.replace(" ", "日 ");
  279.             int index = updateTime.indexOf("0");
  280.             if (index == 0) {
  281.                 updateTime = updateTime.substring(index + 1);
  282.             }
  283.             holder.text3.setText(updateTime);
  284.         }
  285.         // 来自那种客户端
  286.         Source source = freshNews.getSource();
  287.         if (source != null) {
  288.             holder.text4.setText("来自:" + source.getText());
  289.         }
  290.         return convertView;
  291.     }
  292.     static class ViewHolder {
  293.         public LinearLayout linearLayout1;
  294.         public LinearLayout linearLayout2;
  295.         public LinearLayout linearLayout3;
  296.         public LinearLayout linearLayout4;
  297.         public ImageView imageView1;
  298.         public ImageView imageView2;
  299.         public ImageView imageView3;
  300.         public TextView text1;
  301.         public TextView text2;
  302.         public TextView text3;
  303.         public TextView text4;
  304.         public TextView text5;
  305.         public TextView text6;
  306.         public TextView text7;
  307.         public TextView text8;
  308.         public TextView text9;
  309.         public TextView text10;
  310.         public TextView text11;
  311.         public TextView text12;
  312.     }
  313. }

2、新鲜事视图完整源码如下:

 

 

[java][/java] view plaincopy

  1. package com.everyone.android.ui.freshnews;
  2. import java.text.SimpleDateFormat;
  3. import java.util.HashMap;
  4. import java.util.LinkedList;
  5. import java.util.List;
  6. import java.util.Map;
  7. import org.json.JSONException;
  8. import android.content.Context;
  9. import android.os.Handler;
  10. import android.util.AttributeSet;
  11. import android.view.LayoutInflater;
  12. import android.view.View;
  13. import android.view.View.OnClickListener;
  14. import android.widget.AdapterView;
  15. import android.widget.AdapterView.OnItemClickListener;
  16. import android.widget.FrameLayout;
  17. import android.widget.LinearLayout;
  18. import android.widget.ListView;
  19. import android.widget.PopupWindow;
  20. import android.widget.Toast;
  21. import com.everyone.android.R;
  22. import com.everyone.android.api.AuthTokenManager;
  23. import com.everyone.android.callback.ParseCallback;
  24. import com.everyone.android.callback.ResultCallback;
  25. import com.everyone.android.entity.FreshNews;
  26. import com.everyone.android.net.AsyncBaseRequest;
  27. import com.everyone.android.net.AsyncHttpsPost;
  28. import com.everyone.android.net.DefaultThreadPool;
  29. import com.everyone.android.ui.EveryoneActivity;
  30. import com.everyone.android.utils.Constant;
  31. import com.everyone.android.utils.LogUtil;
  32. import com.everyone.android.widget.TopMenuNavbar;
  33. import com.everyone.android.widget.XListView;
  34. import com.everyone.android.widget.XListView.IXListViewListener;
  35. import com.google.gson.Gson;
  36. import com.google.gson.reflect.TypeToken;
  37. /**
  38.  * 功能描述:新鲜事视图
  39.  * @author android_ls
  40.  */
  41. public class FreshNewsLayout extends FrameLayout implements IXListViewListener, OnClickListener {
  42.     /**
  43.      * LOG打印标签
  44.      */
  45.     private static final String TAG = "FreshNewsLayout";
  46.     private TopMenuNavbar topMenuNavbar;
  47.     /**
  48.      * 每一页记录数,默认值为30,最大50
  49.      */
  50.     private int pageCount = 30;
  51.     /**
  52.      * 当前获取第几页,默认值为1
  53.      */
  54.     private int page = 1;
  55.     public TopMenuNavbar getTopMenuNavbar() {
  56.         return topMenuNavbar;
  57.     }
  58.     private EveryoneActivity mActivity;
  59.     private List<AsyncBaseRequest> mAsyncRequests;
  60.     private DefaultThreadPool mDefaultThreadPool;
  61.     private Handler mHandler;
  62.     public AuthTokenManager mAuthTokenManager;
  63.     private LinearLayout mLoadingView;
  64.     private XListView mListView;
  65.     private FreshNewsAdapter mFreshNewsAdapter;
  66.     /**
  67.      * 新鲜事信息集合
  68.      */
  69.     private LinkedList<FreshNews> mFreshNewsList = new LinkedList<FreshNews>();
  70.     private PopupWindow mPopupWindow;
  71.     /**
  72.      * 顶部下拉列表
  73.      */
  74.     private ListView mPopupListView;
  75.     /**
  76.      * 顶部下拉列表数据适配器
  77.      */
  78.     private FreshNewsPopupAdapter mPopupAdapter;
  79.     /**
  80.      * 顶部下拉列表的操作提示文本数组
  81.      */
  82.     private String[] mTexts;
  83.     /**
  84.      * 顶部下拉列表的操作指示图标Id数组
  85.      */
  86.     private int[] mIcons = {
  87.             R.drawable.v5_0_1_newsfeed_popupwindow_type_all_background,
  88.             R.drawable.v5_0_1_newsfeed_popupwindow_type_friend_background,
  89.             R.drawable.v5_0_1_newsfeed_popupwindow_type_specialfocus_background,
  90.             R.drawable.v5_0_1_newsfeed_popupwindow_type_status_background,
  91.             R.drawable.v5_0_1_newsfeed_popupwindow_type_photo_background,
  92.             R.drawable.v5_0_1_newsfeed_popupwindow_type_place_background,
  93.             R.drawable.v5_0_1_newsfeed_popupwindow_type_share_background,
  94.             R.drawable.v5_0_1_newsfeed_popupwindow_type_blog_background };
  95.     /* 10 更新状态的新鲜事。
  96.     11 page更新状态的新鲜事。
  97.     20 发表日志的新鲜事。
  98.     21 分享日志的新鲜事。
  99.     22 page发表日志的新鲜事。
  100.     23 page分享日志的新鲜事。
  101.     30 上传照片的新鲜事。
  102.     31 page上传照片的新鲜事。
  103.     32 分享照片的新鲜事。
  104.     33 分享相册的新鲜事。
  105.     34 修改头像的新鲜事。
  106.     35 page修改头像的新鲜事。
  107.     36 page分享照片的新鲜事。
  108.     40 成为好友的新鲜事。
  109.     41 成为page粉丝的新鲜事。
  110.     50 分享视频的新鲜事。
  111.     51 分享链接的新鲜事。
  112.     52 分享音乐的新鲜事。
  113.     53 page分享视频的新鲜事。
  114.     54 page分享链接的新鲜事。
  115.     55 page分享音乐的新鲜事。
  116.     */
  117.     /**
  118.      * 发表的新鲜事,默认请求所有类型的新鲜事
  119.      */
  120.     private static final String FRESH_NEWS_TYPE_ALL = "10,11,20,21,22,23,30,31,32,33,34,35,36";
  121.     /**
  122.      * 好友内容
  123.      */
  124.     private static final String FRESH_NEWS_TYPE_FRIEND = "40";
  125.     /**
  126.      * 特别关注
  127.      */
  128.     private static final String FRESH_NEWS_TYPE_FOCUS = null;
  129.     /**
  130.      * 状态
  131.      */
  132.     private static final String FRESH_NEWS_TYPE_STATUS = "10,11";
  133.     /**
  134.      * 照片
  135.      */
  136.     private static final String FRESH_NEWS_TYPE_PHOTO = "30,31";
  137.     /**
  138.      * 位置
  139.      */
  140.     private static final String FRESH_NEWS_TYPE_PLACE = null;
  141.     /**
  142.      * 分享的新鲜事
  143.      */
  144.     private static final String FRESH_NEWS_TYPE_SHARE = "21,23,32,33,36";
  145.     /**
  146.      * 日志
  147.      */
  148.     private static final String FRESH_NEWS_TYPE_BLOG = "20,22";
  149.     /**
  150.      * 新鲜事类型数组
  151.      */
  152.     private String[] freshNewsTypes = {FRESH_NEWS_TYPE_ALL, FRESH_NEWS_TYPE_FRIEND,
  153.             FRESH_NEWS_TYPE_FOCUS, FRESH_NEWS_TYPE_STATUS,FRESH_NEWS_TYPE_PHOTO,
  154.             FRESH_NEWS_TYPE_PLACE, FRESH_NEWS_TYPE_SHARE,FRESH_NEWS_TYPE_BLOG};
  155.     /**
  156.      * 新鲜事类型,默认为当前所支持的全部类型
  157.      */
  158.     private String fresh_news_type = FRESH_NEWS_TYPE_ALL;
  159.     private SimpleDateFormat mDateFormat;
  160.     public FreshNewsLayout(EveryoneActivity activity) {
  161.         super(activity);
  162.         mActivity = activity;
  163.         this.mAsyncRequests = activity.getAsyncRequests();
  164.         this.mDefaultThreadPool = activity.getDefaultThreadPool();
  165.         this.mHandler = activity.getHandler();
  166.         this.mAuthTokenManager = activity.getAuthTokenManager();
  167.         mDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
  168.         setupViews();
  169.         // 初始化下拉列表
  170.         setupPopupWindow();
  171.     }
  172.     public FreshNewsLayout(Context context, AttributeSet attrs) {
  173.        super(context, attrs);
  174.        setupViews();
  175.     }
  176.     private void setupPopupWindow() {
  177.         mTexts = mActivity.getResources().getStringArray(R.array.fresh_news_filter_list);
  178.         View view = LayoutInflater.from(mActivity).inflate(R.layout.fresh_news_popupwindow, null);
  179.         mPopupWindow = new PopupWindow(view, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, true);
  180.         mPopupWindow.setAnimationStyle(R.style.fresh_news_popup_animation);
  181.         mPopupListView = (ListView) view.findViewById(R.id.popup_listview);
  182.         mPopupAdapter = new FreshNewsPopupAdapter(mActivity, mIcons, mTexts);
  183.         mPopupListView.setAdapter(mPopupAdapter);
  184.         mPopupListView.setOnItemClickListener(new OnItemClickListener() {
  185.             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  186.                 mPopupWindow.dismiss();
  187.                 // 当前选择的项与之前的一样,则不做处理。
  188.                 if (mPopupAdapter.getPosition() == position) {
  189.                     return;
  190.                 }
  191.                 // 新鲜事过滤事件处理
  192.                 fresh_news_type = freshNewsTypes[position];
  193.                 LogUtil.i(TAG, "onItemClick position = " + position);
  194.                 LogUtil.i(TAG, "onItemClick fresh_news_type = " + fresh_news_type);
  195.                 if(fresh_news_type == null){
  196.                     Toast.makeText(mActivity.getApplicationContext(), "抱歉,您选择的项官方API暂时未提供如何获取相应的数据!", Toast.LENGTH_LONG).show();
  197.                     return;
  198.                 }
  199.                 mPopupAdapter.setPosition(position);
  200.                 mPopupAdapter.notifyDataSetChanged();
  201.                 topMenuNavbar.tvTitle.setText(mTexts[position]);
  202.                 page = 1;
  203.                 mFreshNewsList.clear();
  204.                 getFreshNews();
  205.             }
  206.         });
  207.     }
  208.     private void setupViews() {
  209.         final LayoutInflater mLayoutInflater = LayoutInflater.from(getContext());
  210.         LinearLayout freshNewsViewRoot = (LinearLayout) mLayoutInflater.inflate(R.layout.fresh_news, null);
  211.         addView(freshNewsViewRoot);
  212.         // 加载提示进度条
  213.         mLoadingView = (LinearLayout) freshNewsViewRoot.findViewById(R.id.loading);
  214.         topMenuNavbar = (TopMenuNavbar) freshNewsViewRoot.findViewById(R.id.rl_top_menu_navbar);
  215.         topMenuNavbar.mLlDownList.setOnClickListener(this);
  216.         topMenuNavbar.mLlRefresh.setOnClickListener(this);
  217.         topMenuNavbar.ivRightLine.setVisibility(View.GONE);
  218.         topMenuNavbar.tvRightOperationName.setVisibility(View.GONE);
  219.         mListView = (XListView) freshNewsViewRoot.findViewById(R.id.listview);
  220.         mListView.setPullLoadEnable(false);
  221.         mListView.setPullRefreshEnable(false);
  222.         mListView.setXListViewListener(this);
  223.         mFreshNewsAdapter = new FreshNewsAdapter(mActivity, mFreshNewsList);
  224.         mListView.setAdapter(mFreshNewsAdapter);
  225.     }
  226.     @Override
  227.     public void onClick(View v) {
  228.         switch (v.getId()) {
  229.         case R.id.ll_down_list:
  230.             if (mPopupWindow != null) {
  231.                 mPopupWindow.showAsDropDown(topMenuNavbar);
  232.             }
  233.             break;
  234.         case R.id.ll_refresh:
  235.             // mHeaderView.setState(XListViewHeader.STATE_REFRESHING);
  236.             // page = 1;
  237.             // getFreshNews();
  238.             break;
  239.         default:
  240.             break;
  241.         }
  242.     }
  243.     // 下拉刷新
  244.     @Override
  245.     public void onRefresh() {
  246.         page = 1;
  247.         getFreshNews();
  248.     }
  249.     // 加载更多
  250.     @Override
  251.     public void onLoadMore() {
  252.         page++;
  253.         getFreshNews();
  254.     }
  255.     /**
  256.      * 向服务器端请求新鲜事的数据
  257.      */
  258.     public void getFreshNews() {
  259.         String accessToken = mAuthTokenManager.getAccessToken();
  260.         LogUtil.e(TAG, "accessToken = " + accessToken);
  261.         Map<String, String> parameter = new HashMap<String, String>();
  262.         parameter.put("v", "1.0"); // API的版本号,固定值为1.0
  263.         parameter.put("access_token", accessToken); // OAuth2.0验证授权后获得的token。
  264.         parameter.put("format", "JSON"); // 返回值的格式。请指定为JSON或者XML
  265.         parameter.put("call_id", "1.0"); // 请求队列号
  266.         parameter.put("method", "feed.get");
  267.         parameter.put("type", fresh_news_type); // 新鲜事的类别,多个类型以逗号分隔,type列表
  268.         // parameter.put("uid", ""); // 支持传入当前用户的一个好友ID,表示获取此好友的新鲜事,如果不传,默认为获取当前用户的新鲜事
  269.         parameter.put("page", page + ""); // 支持分页,指定页号,页号从1开始,默认值为1
  270.         parameter.put("count", pageCount + ""); // 支持分页,每一页记录数,默认值为30,最大50
  271.         AsyncHttpsPost asyncHttpsPost = new AsyncHttpsPost(Constant.API_SERVER_URL, parameter, new ParseCallback() {
  272.             @Override
  273.             public LinkedList<FreshNews> parse(String json) throws JSONException {
  274.                 LogUtil.i(TAG, "json = " + json);
  275.                 if ("[]".equals(json)) {
  276.                     return null;
  277.                 }
  278.                 Gson gson = new Gson();
  279.                 java.lang.reflect.Type type = new TypeToken<LinkedList<FreshNews>>() {
  280.                 }.getType();
  281.                 LinkedList<FreshNews> freshNewsList = gson.fromJson(json, type);
  282.                 LogUtil.e(TAG, "freshNewsList = " + freshNewsList.size());
  283.                 return freshNewsList;
  284.             }
  285.         }, new ResultCallback() {
  286.             @Override
  287.             public void onSuccess(final Object obj) {
  288.                 mHandler.post(new Runnable() {
  289.                     @Override
  290.                     public void run() {
  291.                         if (obj != null && obj instanceof LinkedList) {
  292.                             @SuppressWarnings("unchecked")
  293.                             LinkedList<FreshNews> freshNewsList = (LinkedList<FreshNews>) obj;
  294.                             if (freshNewsList.size() > 0) {
  295.                                 // 下拉刷新的数据去重复处理
  296.                                 if (page == 1 && mFreshNewsList.size() > 0) {
  297.                                     for (FreshNews freshNews : freshNewsList) {
  298.                                         boolean flage = false;
  299.                                         for (FreshNews fresh : mFreshNewsList) {
  300.                                             if(freshNews.getPost_id() == fresh.getPost_id()){
  301.                                                 flage = true;
  302.                                             }
  303.                                         }
  304.                                         if(flage == false){
  305.                                             mFreshNewsList.addFirst(freshNews);
  306.                                         }
  307.                                     }
  308.                                 } else {
  309.                                     mFreshNewsList.addAll(freshNewsList);
  310.                                 }
  311.                                 mListView.setPullLoadEnable(true);
  312.                                 mListView.setPullRefreshEnable(true);
  313.                             }
  314.                         } else {
  315.                             mListView.setPullLoadEnable(false);
  316.                         }
  317.                         if (page == 1) {
  318.                             if (mLoadingView.isShown()) {
  319.                                 mLoadingView.setVisibility(View.GONE);
  320.                             }
  321.                             mFreshNewsAdapter.notifyDataSetInvalidated();
  322.                             mListView.stopRefresh();
  323.                         } else {
  324.                             mFreshNewsAdapter.notifyDataSetChanged();
  325.                             mListView.stopLoadMore();
  326.                         }
  327.                         // 设置刷新时间
  328.                         String refreshTime = mDateFormat.format(System.currentTimeMillis());
  329.                         mListView.setRefreshTime(refreshTime);
  330.                     }
  331.                 });
  332.             }
  333.             @Override
  334.             public void onFail(int errorCode) {
  335.                 LogUtil.i(TAG, "freshNewsList errorCode = " + errorCode);
  336.             }
  337.         });
  338.         mDefaultThreadPool.execute(asyncHttpsPost);
  339.         mAsyncRequests.add(asyncHttpsPost);
  340.     }
  341. }

3、新鲜事视图顶部,下拉列表数据适配器的完整源码如下:

 

 

[java][/java] view plaincopy

  1. package com.everyone.android.ui.freshnews;
  2. import android.content.Context;
  3. import android.view.LayoutInflater;
  4. import android.view.View;
  5. import android.view.ViewGroup;
  6. import android.widget.BaseAdapter;
  7. import android.widget.CheckBox;
  8. import android.widget.ImageView;
  9. import com.everyone.android.R;
  10. /**
  11.  * 功能描述:新鲜事视图顶部下拉列表数据适配器
  12.  * @author android_ls
  13.  *
  14.  */
  15. public class FreshNewsPopupAdapter extends BaseAdapter {
  16.     private LayoutInflater mInflater;
  17.     private int[] mIcon;
  18.     private String[] mName;
  19.     private int mPosition;
  20.     public int getPosition() {
  21.         return mPosition;
  22.     }
  23.     public void setPosition(int mPosition) {
  24.         this.mPosition = mPosition;
  25.     }
  26.     public FreshNewsPopupAdapter(Context context, int[] icon, String[] name) {
  27.         mInflater = LayoutInflater.from(context);
  28.         mIcon = icon;
  29.         mName = name;
  30.     }
  31.     public int getCount() {
  32.         return mIcon.length;
  33.     }
  34.     public Object getItem(int position) {
  35.         return null;
  36.     }
  37.     public long getItemId(int position) {
  38.         return position;
  39.     }
  40.     public View getView(int position, View convertView, ViewGroup parent) {
  41.         ViewHolder holder = null;
  42.         if (convertView == null) {
  43.             convertView = mInflater.inflate(R.layout.fresh_news_popupwindow_item, null);
  44.             holder = new ViewHolder();
  45.             holder.checkBox = (CheckBox) convertView.findViewById(R.id.cb_text_icon);
  46.             holder.imageView = (ImageView) convertView.findViewById(R.id.iv_checked);
  47.             convertView.setTag(holder);
  48.         } else {
  49.             holder = (ViewHolder) convertView.getTag();
  50.         }
  51.         holder.checkBox.setButtonDrawable(mIcon[position]);
  52.         holder.checkBox.setText(mName[position]);
  53.         holder.checkBox.setChecked(false);
  54.         holder.imageView.setVisibility(View.GONE);
  55.         if (position == mPosition) {
  56.             holder.checkBox.setChecked(true);
  57.             holder.imageView.setVisibility(View.VISIBLE);
  58.         }
  59.         return convertView;
  60.     }
  61.     static class ViewHolder {
  62.         CheckBox checkBox;
  63.         ImageView imageView;
  64.     }
  65. }

四、开源组件的源码

1、XListView组件的源码:

[java][/java] view plaincopy

  1. /**
  2.  * @file XListView.java
  3.  * @package me.maxwin.view
  4.  * @create Mar 18, 2012 6:28:41 PM
  5.  * @author Maxwin
  6.  * @description An ListView support (a) Pull down to refresh, (b) Pull up to load more.
  7.  *      Implement IXListViewListener, and see stopRefresh() / stopLoadMore().
  8.  */
  9. package com.everyone.android.widget;
  10. import android.content.Context;
  11. import android.util.AttributeSet;
  12. import android.view.MotionEvent;
  13. import android.view.View;
  14. import android.view.ViewTreeObserver.OnGlobalLayoutListener;
  15. import android.view.animation.DecelerateInterpolator;
  16. import android.widget.AbsListView;
  17. import android.widget.AbsListView.OnScrollListener;
  18. import android.widget.ListAdapter;
  19. import android.widget.ListView;
  20. import android.widget.RelativeLayout;
  21. import android.widget.Scroller;
  22. import android.widget.TextView;
  23. import com.everyone.android.R;
  24. public class XListView extends ListView implements OnScrollListener {
  25.     private float mLastY = -1; // save event y
  26.     private Scroller mScroller; // used for scroll back
  27.     private OnScrollListener mScrollListener; // user's scroll listener
  28.     // the interface to trigger refresh and load more.
  29.     private IXListViewListener mListViewListener;
  30.     // -- header view
  31.     private XListViewHeader mHeaderView;
  32.     // header view content, use it to calculate the Header's height. And hide it
  33.     // when disable pull refresh.
  34.     private RelativeLayout mHeaderViewContent;
  35.     private TextView mHeaderTimeView;
  36.     private int mHeaderViewHeight; // header view's height
  37.     private boolean mEnablePullRefresh = true;
  38.     private boolean mPullRefreshing = false; // is refreashing.
  39.     // -- footer view
  40.     private XListViewFooter mFooterView;
  41.     private boolean mEnablePullLoad;
  42.     private boolean mPullLoading;
  43.     private boolean mIsFooterReady = false;
  44.     // total list items, used to detect is at the bottom of listview.
  45.     private int mTotalItemCount;
  46.     // for mScroller, scroll back from header or footer.
  47.     private int mScrollBack;
  48.     private final static int SCROLLBACK_HEADER = 0;
  49.     private final static int SCROLLBACK_FOOTER = 1;
  50.     private final static int SCROLL_DURATION = 400; // scroll back duration
  51.     private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px
  52.                                                         // at bottom, trigger
  53.                                                         // load more.
  54.     private final static float OFFSET_RADIO = 1.8f; // support iOS like pull
  55.                                                     // feature.
  56.     /**
  57.      * @param context
  58.      */
  59.     public XListView(Context context) {
  60.         super(context);
  61.         initWithContext(context);
  62.     }
  63.     public XListView(Context context, AttributeSet attrs) {
  64.         super(context, attrs);
  65.         initWithContext(context);
  66.     }
  67.     public XListView(Context context, AttributeSet attrs, int defStyle) {
  68.         super(context, attrs, defStyle);
  69.         initWithContext(context);
  70.     }
  71.     private void initWithContext(Context context) {
  72.         mScroller = new Scroller(context, new DecelerateInterpolator());
  73.         // XListView need the scroll event, and it will dispatch the event to
  74.         // user's listener (as a proxy).
  75.         super.setOnScrollListener(this);
  76.         // init header view
  77.         mHeaderView = new XListViewHeader(context);
  78.         mHeaderViewContent = (RelativeLayout) mHeaderView.findViewById(R.id.xlistview_header_content);
  79.         mHeaderTimeView = (TextView) mHeaderView.findViewById(R.id.xlistview_header_time);
  80.         addHeaderView(mHeaderView);
  81.         // init footer view
  82.         mFooterView = new XListViewFooter(context);
  83.         // init header height
  84.         mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  85.             @Override
  86.             public void onGlobalLayout() {
  87.                 mHeaderViewHeight = mHeaderViewContent.getHeight();
  88.                 getViewTreeObserver().removeGlobalOnLayoutListener(this);
  89.             }
  90.         });
  91.     }
  92.     @Override
  93.     public void setAdapter(ListAdapter adapter) {
  94.         // make sure XListViewFooter is the last footer view, and only add once.
  95.         if (mIsFooterReady == false) {
  96.             mIsFooterReady = true;
  97.             addFooterView(mFooterView);
  98.         }
  99.         super.setAdapter(adapter);
  100.     }
  101.     /**
  102.      * enable or disable pull down refresh feature.
  103.      *
  104.      * @param enable
  105.      */
  106.     public void setPullRefreshEnable(boolean enable) {
  107.         mEnablePullRefresh = enable;
  108.         if (!mEnablePullRefresh) { // disable, hide the content
  109.             mHeaderViewContent.setVisibility(View.INVISIBLE);
  110.         } else {
  111.             mHeaderViewContent.setVisibility(View.VISIBLE);
  112.         }
  113.     }
  114.     /**
  115.      * enable or disable pull up load more feature.
  116.      *
  117.      * @param enable
  118.      */
  119.     public void setPullLoadEnable(boolean enable) {
  120.         mEnablePullLoad = enable;
  121.         if (!mEnablePullLoad) {
  122.             mFooterView.hide();
  123.             mFooterView.setOnClickListener(null);
  124.         } else {
  125.             mPullLoading = false;
  126.             mFooterView.show();
  127.             mFooterView.setState(XListViewFooter.STATE_NORMAL);
  128.             // both "pull up" and "click" will invoke load more.
  129.             mFooterView.setOnClickListener(new OnClickListener() {
  130.                 @Override
  131.                 public void onClick(View v) {
  132.                     startLoadMore();
  133.                 }
  134.             });
  135.         }
  136.     }
  137.     /**
  138.      * stop refresh, reset header view.
  139.      */
  140.     public void stopRefresh() {
  141.         if (mPullRefreshing == true) {
  142.             mPullRefreshing = false;
  143.             resetHeaderHeight();
  144.         }
  145.     }
  146.     /**
  147.      * stop load more, reset footer view.
  148.      */
  149.     public void stopLoadMore() {
  150.         if (mPullLoading == true) {
  151.             mPullLoading = false;
  152.             mFooterView.setState(XListViewFooter.STATE_NORMAL);
  153.         }
  154.     }
  155.     /**
  156.      * set last refresh time
  157.      *
  158.      * @param time
  159.      */
  160.     public void setRefreshTime(String time) {
  161.         mHeaderTimeView.setText(time);
  162.     }
  163.     private void invokeOnScrolling() {
  164.         if (mScrollListener instanceof OnXScrollListener) {
  165.             OnXScrollListener l = (OnXScrollListener) mScrollListener;
  166.             l.onXScrolling(this);
  167.         }
  168.     }
  169.     private void updateHeaderHeight(float delta) {
  170.         mHeaderView.setVisiableHeight((int) delta + mHeaderView.getVisiableHeight());
  171.         if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头
  172.             if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
  173.                 mHeaderView.setState(XListViewHeader.STATE_READY);
  174.             } else {
  175.                 mHeaderView.setState(XListViewHeader.STATE_NORMAL);
  176.             }
  177.         }
  178.         setSelection(0); // scroll to top each time
  179.     }
  180.     /**
  181.      * reset header view's height.
  182.      */
  183.     private void resetHeaderHeight() {
  184.         int height = mHeaderView.getVisiableHeight();
  185.         if (height == 0) // not visible.
  186.             return;
  187.         // refreshing and header isn't shown fully. do nothing.
  188.         if (mPullRefreshing && height <= mHeaderViewHeight) {
  189.             return;
  190.         }
  191.         int finalHeight = 0; // default: scroll back to dismiss header.
  192.         // is refreshing, just scroll back to show all the header.
  193.         if (mPullRefreshing && height > mHeaderViewHeight) {
  194.             finalHeight = mHeaderViewHeight;
  195.         }
  196.         mScrollBack = SCROLLBACK_HEADER;
  197.         mScroller.startScroll(0, height, 0, finalHeight - height, SCROLL_DURATION);
  198.         // trigger computeScroll
  199.         invalidate();
  200.     }
  201.     private void updateFooterHeight(float delta) {
  202.         int height = mFooterView.getBottomMargin() + (int) delta;
  203.         if (mEnablePullLoad && !mPullLoading) {
  204.             if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load
  205.                                                  // more.
  206.                 mFooterView.setState(XListViewFooter.STATE_READY);
  207.             } else {
  208.                 mFooterView.setState(XListViewFooter.STATE_NORMAL);
  209.             }
  210.         }
  211.         mFooterView.setBottomMargin(height);
  212.         //      setSelection(mTotalItemCount - 1); // scroll to bottom
  213.     }
  214.     private void resetFooterHeight() {
  215.         int bottomMargin = mFooterView.getBottomMargin();
  216.         if (bottomMargin > 0) {
  217.             mScrollBack = SCROLLBACK_FOOTER;
  218.             mScroller.startScroll(0, bottomMargin, 0, -bottomMargin, SCROLL_DURATION);
  219.             invalidate();
  220.         }
  221.     }
  222.     private void startLoadMore() {
  223.         mPullLoading = true;
  224.         mFooterView.setState(XListViewFooter.STATE_LOADING);
  225.         if (mListViewListener != null) {
  226.             mListViewListener.onLoadMore();
  227.         }
  228.     }
  229.     @Override
  230.     public boolean onTouchEvent(MotionEvent ev) {
  231.         if (mLastY == -1) {
  232.             mLastY = ev.getRawY();
  233.         }
  234.         switch (ev.getAction()) {
  235.         case MotionEvent.ACTION_DOWN:
  236.             mLastY = ev.getRawY();
  237.             break;
  238.         case MotionEvent.ACTION_MOVE:
  239.             final float deltaY = ev.getRawY() - mLastY;
  240.             mLastY = ev.getRawY();
  241.             if (getFirstVisiblePosition() == 0 && (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {
  242.                 // the first item is showing, header has shown or pull down.
  243.                 updateHeaderHeight(deltaY / OFFSET_RADIO);
  244.                 invokeOnScrolling();
  245.             } else if (getLastVisiblePosition() == mTotalItemCount - 1 && (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {
  246.                 // last item, already pulled up or want to pull up.
  247.                 updateFooterHeight(-deltaY / OFFSET_RADIO);
  248.             }
  249.             break;
  250.         default:
  251.             mLastY = -1; // reset
  252.             if (getFirstVisiblePosition() == 0) {
  253.                 // invoke refresh
  254.                 if (mEnablePullRefresh && mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
  255.                     mPullRefreshing = true;
  256.                     mHeaderView.setState(XListViewHeader.STATE_REFRESHING);
  257.                     if (mListViewListener != null) {
  258.                         mListViewListener.onRefresh();
  259.                     }
  260.                 }
  261.                 resetHeaderHeight();
  262.             } else if (getLastVisiblePosition() == mTotalItemCount - 1) {
  263.                 // invoke load more.
  264.                 if (mEnablePullLoad && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA) {
  265.                     startLoadMore();
  266.                 }
  267.                 resetFooterHeight();
  268.             }
  269.             break;
  270.         }
  271.         return super.onTouchEvent(ev);
  272.     }
  273.     @Override
  274.     public void computeScroll() {
  275.         if (mScroller.computeScrollOffset()) {
  276.             if (mScrollBack == SCROLLBACK_HEADER) {
  277.                 mHeaderView.setVisiableHeight(mScroller.getCurrY());
  278.             } else {
  279.                 mFooterView.setBottomMargin(mScroller.getCurrY());
  280.             }
  281.             postInvalidate();
  282.             invokeOnScrolling();
  283.         }
  284.         super.computeScroll();
  285.     }
  286.     @Override
  287.     public void setOnScrollListener(OnScrollListener l) {
  288.         mScrollListener = l;
  289.     }
  290.     @Override
  291.     public void onScrollStateChanged(AbsListView view, int scrollState) {
  292.         if (mScrollListener != null) {
  293.             mScrollListener.onScrollStateChanged(view, scrollState);
  294.         }
  295.     }
  296.     @Override
  297.     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
  298.         // send to user's listener
  299.         mTotalItemCount = totalItemCount;
  300.         if (mScrollListener != null) {
  301.             mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
  302.         }
  303.     }
  304.     public void setXListViewListener(IXListViewListener l) {
  305.         mListViewListener = l;
  306.     }
  307.     /**
  308.      * you can listen ListView.OnScrollListener or this one. it will invoke
  309.      * onXScrolling when header/footer scroll back.
  310.      */
  311.     public interface OnXScrollListener extends OnScrollListener {
  312.         public void onXScrolling(View view);
  313.     }
  314.     /**
  315.      * implements this interface to get refresh/load more event.
  316.      */
  317.     public interface IXListViewListener {
  318.         public void onRefresh();
  319.         public void onLoadMore();
  320.     }
  321. }

2、XListViewHeader的源码如下:

 

 

[java][/java] view plaincopy

  1. package com.everyone.android.widget;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.view.Gravity;
  5. import android.view.LayoutInflater;
  6. import android.view.View;
  7. import android.view.animation.Animation;
  8. import android.view.animation.RotateAnimation;
  9. import android.widget.ImageView;
  10. import android.widget.LinearLayout;
  11. import android.widget.ProgressBar;
  12. import android.widget.TextView;
  13. import com.everyone.android.R;
  14. public class XListViewHeader extends LinearLayout {
  15.     private LinearLayout mContainer;
  16.     private ImageView mArrowImageView;
  17.     private ProgressBar mProgressBar;
  18.     private TextView mHintTextView;
  19.     private int mState = STATE_NORMAL;
  20.     private Animation mRotateUpAnim;
  21.     private Animation mRotateDownAnim;
  22.     private final int ROTATE_ANIM_DURATION = 180;
  23.     public final static int STATE_NORMAL = 0;
  24.     public final static int STATE_READY = 1;
  25.     public final static int STATE_REFRESHING = 2;
  26.     public XListViewHeader(Context context) {
  27.         super(context);
  28.         initView(context);
  29.     }
  30.     /**
  31.      * @param context
  32.      * @param attrs
  33.      */
  34.     public XListViewHeader(Context context, AttributeSet attrs) {
  35.         super(context, attrs);
  36.         initView(context);
  37.     }
  38.     private void initView(Context context) {
  39.         // 初始情况,设置下拉刷新view高度为0
  40.         LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
  41.                 LayoutParams.FILL_PARENT, 0);
  42.         mContainer = (LinearLayout) LayoutInflater.from(context).inflate(
  43.                 R.layout.xlistview_header, null);
  44.         addView(mContainer, lp);
  45.         setGravity(Gravity.BOTTOM);
  46.         mArrowImageView = (ImageView)findViewById(R.id.xlistview_header_arrow);
  47.         mHintTextView = (TextView)findViewById(R.id.xlistview_header_hint_textview);
  48.         mProgressBar = (ProgressBar)findViewById(R.id.xlistview_header_progressbar);
  49.         mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
  50.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
  51.                 0.5f);
  52.         mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
  53.         mRotateUpAnim.setFillAfter(true);
  54.         mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
  55.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
  56.                 0.5f);
  57.         mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
  58.         mRotateDownAnim.setFillAfter(true);
  59.     }
  60.     public void setState(int state) {
  61.         if (state == mState) return ;
  62.         if (state == STATE_REFRESHING) {    // 显示进度
  63.             mArrowImageView.clearAnimation();
  64.             mArrowImageView.setVisibility(View.INVISIBLE);
  65.             mProgressBar.setVisibility(View.VISIBLE);
  66.         } else {    // 显示箭头图片
  67.             mArrowImageView.setVisibility(View.VISIBLE);
  68.             mProgressBar.setVisibility(View.INVISIBLE);
  69.         }
  70.         switch(state){
  71.         case STATE_NORMAL:
  72.             if (mState == STATE_READY) {
  73.                 mArrowImageView.startAnimation(mRotateDownAnim);
  74.             }
  75.             if (mState == STATE_REFRESHING) {
  76.                 mArrowImageView.clearAnimation();
  77.             }
  78.             mHintTextView.setText(R.string.xlistview_header_hint_normal);
  79.             break;
  80.         case STATE_READY:
  81.             if (mState != STATE_READY) {
  82.                 mArrowImageView.clearAnimation();
  83.                 mArrowImageView.startAnimation(mRotateUpAnim);
  84.                 mHintTextView.setText(R.string.xlistview_header_hint_ready);
  85.             }
  86.             break;
  87.         case STATE_REFRESHING:
  88.             mHintTextView.setText(R.string.xlistview_header_hint_loading);
  89.             break;
  90.             default:
  91.         }
  92.         mState = state;
  93.     }
  94.     public void setVisiableHeight(int height) {
  95.         if (height < 0)
  96.             height = 0;
  97.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContainer
  98.                 .getLayoutParams();
  99.         lp.height = height;
  100.         mContainer.setLayoutParams(lp);
  101.     }
  102.     public int getVisiableHeight() {
  103.         return mContainer.getHeight();
  104.     }
  105. }

3、XListViewFooter的源码如下:

 

 

[java][/java] view plaincopy

  1. package com.everyone.android.widget;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.widget.LinearLayout;
  7. import android.widget.TextView;
  8. import com.everyone.android.R;
  9. public class XListViewFooter extends LinearLayout {
  10.     public final static int STATE_NORMAL = 0;
  11.     public final static int STATE_READY = 1;
  12.     public final static int STATE_LOADING = 2;
  13.     private Context mContext;
  14.     private View mContentView;
  15.     private View mProgressBar;
  16.     private TextView mHintView;
  17.     private TextView mLoadTextView;
  18.     public XListViewFooter(Context context) {
  19.         super(context);
  20.         initView(context);
  21.     }
  22.     public XListViewFooter(Context context, AttributeSet attrs) {
  23.         super(context, attrs);
  24.         initView(context);
  25.     }
  26.     public void setState(int state) {
  27.         mHintView.setVisibility(View.INVISIBLE);
  28.         mProgressBar.setVisibility(View.INVISIBLE);
  29.         mHintView.setVisibility(View.INVISIBLE);
  30.         mLoadTextView.setVisibility(View.INVISIBLE);
  31.         if (state == STATE_READY) {
  32.             mHintView.setVisibility(View.VISIBLE);
  33.             mHintView.setText(R.string.xlistview_footer_hint_ready);
  34.         } else if (state == STATE_LOADING) {
  35.             mProgressBar.setVisibility(View.VISIBLE);
  36.             mLoadTextView.setVisibility(View.VISIBLE);
  37.         } else {
  38.             mHintView.setVisibility(View.VISIBLE);
  39.             mHintView.setText(R.string.xlistview_footer_hint_normal);
  40.         }
  41.     }
  42.     public void setBottomMargin(int height) {
  43.         if (height < 0) return ;
  44.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
  45.         lp.bottomMargin = height;
  46.         mContentView.setLayoutParams(lp);
  47.     }
  48.     public int getBottomMargin() {
  49.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
  50.         return lp.bottomMargin;
  51.     }
  52.     /**
  53.      * normal status
  54.      */
  55.     public void normal() {
  56.         mHintView.setVisibility(View.VISIBLE);
  57.         mProgressBar.setVisibility(View.GONE);
  58.         mLoadTextView.setVisibility(View.GONE);
  59.     }
  60.     /**
  61.      * loading status
  62.      */
  63.     public void loading() {
  64.         mHintView.setVisibility(View.GONE);
  65.         mProgressBar.setVisibility(View.VISIBLE);
  66.         mLoadTextView.setVisibility(View.VISIBLE);
  67.     }
  68.     /**
  69.      * hide footer when disable pull load more
  70.      */
  71.     public void hide() {
  72.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
  73.         lp.height = 0;
  74.         mContentView.setLayoutParams(lp);
  75.     }
  76.     /**
  77.      * show footer
  78.      */
  79.     public void show() {
  80.         LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
  81.         lp.height = LayoutParams.WRAP_CONTENT;
  82.         mContentView.setLayoutParams(lp);
  83.     }
  84.     private void initView(Context context) {
  85.         mContext = context;
  86.         LinearLayout moreView = (LinearLayout)LayoutInflater.from(mContext).inflate(R.layout.xlistview_footer, null);
  87.         addView(moreView);
  88.         moreView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
  89.         mContentView = moreView.findViewById(R.id.xlistview_footer_content);
  90.         mProgressBar = moreView.findViewById(R.id.xlistview_footer_progressbar);
  91.         mLoadTextView = (TextView)moreView.findViewById(R.id.xlistview_footer_load_textView);
  92.         mHintView = (TextView)moreView.findViewById(R.id.xlistview_footer_hint_textview);
  93.     }
  94. }

xlistview_header.xml文件源码:

 

 

[html][/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="fill_parent"
  4.     android:layout_height="wrap_content"
  5.     android:gravity="bottom" >
  6.     <RelativeLayout
  7.         android:id="@+id/xlistview_header_content"
  8.         android:layout_width="fill_parent"
  9.         android:layout_height="60dp" >
  10.         <LinearLayout
  11.             android:layout_width="wrap_content"
  12.             android:layout_height="wrap_content"
  13.             android:layout_centerInParent="true"
  14.             android:gravity="center"
  15.             android:orientation="vertical" android:id="@+id/xlistview_header_text">
  16.             <TextView
  17.                 android:id="@+id/xlistview_header_hint_textview"
  18.                 android:layout_width="wrap_content"
  19.                 android:layout_height="wrap_content"
  20.                 android:text="@string/xlistview_header_hint_normal" />
  21.             <LinearLayout
  22.                 android:layout_width="wrap_content"
  23.                 android:layout_height="wrap_content"
  24.                 android:layout_marginTop="3dp" >
  25.                 <TextView
  26.                     android:layout_width="wrap_content"
  27.                     android:layout_height="wrap_content"
  28.                     android:text="@string/xlistview_header_last_time"
  29.                     android:textSize="12sp" />
  30.                 <TextView
  31.                     android:id="@+id/xlistview_header_time"
  32.                     android:layout_width="wrap_content"
  33.                     android:layout_height="wrap_content"
  34.                     android:textSize="12sp" />
  35.             </LinearLayout>
  36.         </LinearLayout>
  37.         <ImageView
  38.             android:id="@+id/xlistview_header_arrow"
  39.             android:layout_width="wrap_content"
  40.             android:layout_height="wrap_content"
  41.             android:layout_alignLeft="@id/xlistview_header_text"
  42.             android:layout_centerVertical="true"
  43.             android:layout_marginLeft="-35dp"
  44.             android:src="@drawable/xlistview_arrow" />
  45.         <ProgressBar
  46.             android:id="@+id/xlistview_header_progressbar"
  47.             android:layout_width="30dp"
  48.             android:layout_height="30dp"
  49.             android:layout_alignLeft="@id/xlistview_header_text"
  50.             android:layout_centerVertical="true"
  51.             android:layout_marginLeft="-40dp"
  52.             android:visibility="invisible" />
  53.     </RelativeLayout>
  54. </LinearLayout>

xlistview_footer.xml的源码如下:

 

 

[html][/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="fill_parent"
  4.     android:layout_height="wrap_content" >
  5.     <RelativeLayout
  6.         android:id="@+id/xlistview_footer_content"
  7.         android:layout_width="fill_parent"
  8.         android:layout_height="45dip"
  9.         android:background="#FFFFFF" >
  10.         <TextView
  11.             android:id="@+id/xlistview_footer_hint_textview"
  12.             android:layout_width="wrap_content"
  13.             android:layout_height="wrap_content"
  14.             android:layout_centerInParent="true"
  15.             android:text="@string/xlistview_footer_hint_normal" />
  16.         <LinearLayout
  17.             android:layout_width="fill_parent"
  18.             android:layout_height="45dip"
  19.             android:gravity="center_horizontal|center_vertical"
  20.             android:orientation="horizontal" >
  21.             <ProgressBar
  22.                 android:id="@+id/xlistview_footer_progressbar"
  23.                 android:layout_width="30dip"
  24.                 android:layout_height="30dip" />
  25.             <TextView
  26.                 android:id="@+id/xlistview_footer_load_textView"
  27.                 android:layout_width="wrap_content"
  28.                 android:layout_height="wrap_content"
  29.                 android:paddingLeft="10dip"
  30.                 android:text="正在加载"
  31.                 android:textColor="#000000"
  32.                 android:textSize="15sp" />
  33.         </LinearLayout>
  34.     </RelativeLayout>
  35. </LinearLayout>

strings.xml文件的源码如下:

 

 

[html][/html] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3.     <string name="app_name">CopyEveryone</string>
  4.     <string-array name="left_panel_group_names">
  5.         <item>常用</item>
  6.         <item>更多</item>
  7.         <item>操作</item>
  8.     </string-array>
  9.     <string-array name="left_panel_first_group_names">
  10.         <item>新鲜事</item>
  11.         <item>消息</item>
  12.         <item>聊天</item>
  13.         <item>好友</item>
  14.         <item>找人</item>
  15.     </string-array>
  16.     <string-array name="left_panel_second_group_names">
  17.         <item>附近</item>
  18.         <item>公共主页</item>
  19.         <item>热门分享</item>
  20.         <item>应用与游戏</item>
  21.     </string-array>
  22.     <string-array name="left_panel_group_three_names">
  23.         <item>选项</item>
  24.         <item>注销登录</item>
  25.     </string-array>
  26.     <string-array name="fresh_news_filter_list">
  27.         <item>新鲜事</item>
  28.         <item>好友内容</item>
  29.         <item>特别关注</item>
  30.         <item>状态</item>
  31.         <item>照片</item>
  32.         <item>位置</item>
  33.         <item>分享</item>
  34.         <item>日志</item>
  35.     </string-array>
  36.     <string name="xlistview_header_hint_normal">下拉刷新</string>
  37.     <string name="xlistview_header_hint_ready">松开刷新数据</string>
  38.     <string name="xlistview_header_hint_loading">正在加载</string>
  39.     <string name="xlistview_header_last_time">上次更新时间:</string>
  40.     <string name="xlistview_footer_hint_normal">查看更多</string>
  41.     <string name="xlistview_footer_hint_ready">松开载入更多</string>
  42. </resources>

开源组件XListView的demo的下载地址:http://download.csdn.net/detail/android_ls/5689663


本文固定链接: http://www.devba.com/index.php/archives/1525.html | 开发吧

报歉!评论已关闭.