Android ListView 下拉刷新 点击加载更多

最近项目中用到了ListView的下拉刷新的功能,总结了一下前辈们的代码,单独抽取出来写了一个demo作为示例。

效果图

下拉刷新:

加载更多:

CustomListView.java

[java] view plaincopy

  1. package com.example.uitest.view;
  2. import java.util.Date;
  3. import com.example.uitest.R;
  4. import android.content.Context;
  5. import android.util.AttributeSet;
  6. import android.util.Log;
  7. import android.view.LayoutInflater;
  8. import android.view.MotionEvent;
  9. import android.view.View;
  10. import android.view.ViewGroup;
  11. import android.view.animation.LinearInterpolator;
  12. import android.view.animation.RotateAnimation;
  13. import android.widget.AbsListView;
  14. import android.widget.AbsListView.OnScrollListener;
  15. import android.widget.BaseAdapter;
  16. import android.widget.ImageView;
  17. import android.widget.LinearLayout;
  18. import android.widget.ListView;
  19. import android.widget.ProgressBar;
  20. import android.widget.TextView;
  21. /**
  22. * ListView下拉刷新
  23. *
  24. */
  25. public class CustomListView extends ListView implements OnScrollListener {
  26. private final static int RELEASE_To_REFRESH = 0;
  27. private final static int PULL_To_REFRESH = 1;
  28. private final static int REFRESHING = 2;
  29. private final static int DONE = 3;
  30. private final static int LOADING = 4;
  31. // 实际的padding的距离与界面上偏移距离的比例
  32. private final static int RATIO = 3;
  33. private LayoutInflater inflater;
  34. private LinearLayout headView;
  35. private TextView tipsTextview;
  36. private TextView lastUpdatedTextView;
  37. private ImageView arrowImageView;
  38. private ProgressBar progressBar;
  39. private RotateAnimation animation;
  40. private RotateAnimation reverseAnimation;
  41. // 用于保证startY的值在一个完整的touch事件中只被记录一次
  42. private boolean isRecored;
  43. private int headContentWidth;
  44. private int headContentHeight;
  45. private int startY;
  46. private int firstItemIndex;
  47. private int state;
  48. private boolean isBack;
  49. private OnRefreshListener refreshListener;
  50. private OnLoadListener loadListener;
  51. private boolean isRefreshable;
  52. private ProgressBar moreProgressBar;
  53. private TextView loadMoreView;
  54. private View moreView;
  55. public CustomListView(Context context) {
  56. super(context);
  57. init(context);
  58. }
  59. public CustomListView(Context context, AttributeSet attrs) {
  60. super(context, attrs);
  61. init(context);
  62. }
  63. private void init(Context context) {
  64. setCacheColorHint(context.getResources().getColor(R.color.transparent));
  65. inflater = LayoutInflater.from(context);
  66. headView = (LinearLayout) inflater.inflate(R.layout.head, null);
  67. arrowImageView = (ImageView) headView.findViewById(R.id.head_arrowImageView);
  68. arrowImageView.setMinimumWidth(70);
  69. arrowImageView.setMinimumHeight(50);
  70. progressBar = (ProgressBar) headView.findViewById(R.id.head_progressBar);
  71. tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
  72. lastUpdatedTextView = (TextView) headView.findViewById(R.id.head_lastUpdatedTextView);
  73. measureView(headView);
  74. headContentHeight = headView.getMeasuredHeight();
  75. headContentWidth = headView.getMeasuredWidth();
  76. headView.setPadding(0, -1 * headContentHeight, 0, 0);
  77. headView.invalidate();
  78. Log.v("size", "width:" + headContentWidth + " height:" + headContentHeight);
  79. addHeaderView(headView, null, false);
  80. setOnScrollListener(this);
  81. animation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
  82. animation.setInterpolator(new LinearInterpolator());
  83. animation.setDuration(250);
  84. animation.setFillAfter(true);
  85. reverseAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
  86. reverseAnimation.setInterpolator(new LinearInterpolator());
  87. reverseAnimation.setDuration(200);
  88. reverseAnimation.setFillAfter(true);
  89. state = DONE;
  90. isRefreshable = false;
  91. moreView = LayoutInflater.from(context).inflate(R.layout.listfooter_more, null);
  92. moreView.setVisibility(View.VISIBLE);
  93. moreProgressBar = (ProgressBar) moreView.findViewById(R.id.pull_to_refresh_progress);
  94. loadMoreView = (TextView) moreView.findViewById(R.id.load_more);
  95. moreView.setOnClickListener(new View.OnClickListener() {
  96. @Override
  97. public void onClick(View v) {
  98. onLoad();
  99. }
  100. });
  101. addFooterView(moreView);
  102. }
  103. public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2, int arg3) {
  104. firstItemIndex = firstVisiableItem;
  105. }
  106. public void onScrollStateChanged(AbsListView arg0, int arg1) {
  107. }
  108. public boolean onTouchEvent(MotionEvent event) {
  109. if (isRefreshable) {
  110. switch (event.getAction()) {
  111. case MotionEvent.ACTION_DOWN:
  112. if (firstItemIndex == 0 && !isRecored) {
  113. isRecored = true;
  114. startY = (int) event.getY();
  115. }
  116. break;
  117. case MotionEvent.ACTION_UP:
  118. if (state != REFRESHING && state != LOADING) {
  119. if (state == DONE) {
  120. }
  121. if (state == PULL_To_REFRESH) {
  122. state = DONE;
  123. changeHeaderViewByState();
  124. }
  125. if (state == RELEASE_To_REFRESH) {
  126. state = REFRESHING;
  127. changeHeaderViewByState();
  128. onRefresh();
  129. }
  130. }
  131. isRecored = false;
  132. isBack = false;
  133. break;
  134. case MotionEvent.ACTION_MOVE:
  135. int tempY = (int) event.getY();
  136. if (!isRecored && firstItemIndex == 0) {
  137. isRecored = true;
  138. startY = tempY;
  139. }
  140. if (state != REFRESHING && isRecored && state != LOADING) {
  141. // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
  142. // 可以松手去刷新了
  143. if (state == RELEASE_To_REFRESH) {
  144. setSelection(0);
  145. // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
  146. if (((tempY - startY) / RATIO < headContentHeight) && (tempY - startY) > 0) {
  147. state = PULL_To_REFRESH;
  148. changeHeaderViewByState();
  149. }
  150. // 一下子推到顶了
  151. else if (tempY - startY <= 0) {
  152. state = DONE;
  153. changeHeaderViewByState();
  154. }
  155. // 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
  156. }
  157. // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
  158. if (state == PULL_To_REFRESH) {
  159. setSelection(0);
  160. // 下拉到可以进入RELEASE_TO_REFRESH的状态
  161. if ((tempY - startY) / RATIO >= headContentHeight) {
  162. state = RELEASE_To_REFRESH;
  163. isBack = true;
  164. changeHeaderViewByState();
  165. }
  166. else if (tempY - startY <= 0) {
  167. state = DONE;
  168. changeHeaderViewByState();
  169. }
  170. }
  171. if (state == DONE) {
  172. if (tempY - startY > 0) {
  173. state = PULL_To_REFRESH;
  174. changeHeaderViewByState();
  175. }
  176. }
  177. if (state == PULL_To_REFRESH) {
  178. headView.setPadding(0, -1 * headContentHeight + (tempY - startY) / RATIO, 0, 0);
  179. }
  180. if (state == RELEASE_To_REFRESH) {
  181. headView.setPadding(0, (tempY - startY) / RATIO - headContentHeight, 0, 0);
  182. }
  183. }
  184. break;
  185. }
  186. }
  187. return super.onTouchEvent(event);
  188. }
  189. // 当状态改变时候,调用该方法,以更新界面
  190. private void changeHeaderViewByState() {
  191. switch (state) {
  192. case RELEASE_To_REFRESH:
  193. arrowImageView.setVisibility(View.VISIBLE);
  194. progressBar.setVisibility(View.GONE);
  195. tipsTextview.setVisibility(View.VISIBLE);
  196. lastUpdatedTextView.setVisibility(View.VISIBLE);
  197. arrowImageView.clearAnimation();
  198. arrowImageView.startAnimation(animation);
  199. tipsTextview.setText("松开刷新");
  200. break;
  201. case PULL_To_REFRESH:
  202. progressBar.setVisibility(View.GONE);
  203. tipsTextview.setVisibility(View.VISIBLE);
  204. lastUpdatedTextView.setVisibility(View.VISIBLE);
  205. arrowImageView.clearAnimation();
  206. arrowImageView.setVisibility(View.VISIBLE);
  207. // 是由RELEASE_To_REFRESH状态转变来的
  208. if (isBack) {
  209. isBack = false;
  210. arrowImageView.clearAnimation();
  211. arrowImageView.startAnimation(reverseAnimation);
  212. tipsTextview.setText("下拉刷新");
  213. } else {
  214. tipsTextview.setText("下拉刷新");
  215. }
  216. break;
  217. case REFRESHING:
  218. headView.setPadding(0, 0, 0, 0);
  219. progressBar.setVisibility(View.VISIBLE);
  220. arrowImageView.clearAnimation();
  221. arrowImageView.setVisibility(View.GONE);
  222. tipsTextview.setText("正在刷新...");
  223. lastUpdatedTextView.setVisibility(View.VISIBLE);
  224. break;
  225. case DONE:
  226. headView.setPadding(0, -1 * headContentHeight, 0, 0);
  227. progressBar.setVisibility(View.GONE);
  228. arrowImageView.clearAnimation();
  229. arrowImageView.setImageResource(R.drawable.arrow);
  230. tipsTextview.setText("下拉刷新");
  231. lastUpdatedTextView.setVisibility(View.VISIBLE);
  232. break;
  233. }
  234. }
  235. public void setonRefreshListener(OnRefreshListener refreshListener) {
  236. this.refreshListener = refreshListener;
  237. isRefreshable = true;
  238. }
  239. public void setonLoadListener(OnLoadListener loadListener) {
  240. this.loadListener = loadListener;
  241. }
  242. public interface OnRefreshListener {
  243. public void onRefresh();
  244. }
  245. public interface OnLoadListener {
  246. public void onLoad();
  247. }
  248. @SuppressWarnings("deprecation")
  249. public void onRefreshComplete() {
  250. state = DONE;
  251. lastUpdatedTextView.setText("最近更新:" + new Date().toLocaleString());
  252. changeHeaderViewByState();
  253. }
  254. private void onLoad() {
  255. if (loadListener != null) {
  256. moreProgressBar.setVisibility(View.VISIBLE);
  257. loadMoreView.setText(getContext().getString(R.string.load_more));
  258. loadListener.onLoad();
  259. }
  260. }
  261. public void onLoadComplete() {
  262. //      moreView.setVisibility(View.GONE);
  263. moreProgressBar.setVisibility(View.GONE);
  264. loadMoreView.setText(getContext().getString(R.string.more_data));
  265. }
  266. private void onRefresh() {
  267. if (refreshListener != null) {
  268. refreshListener.onRefresh();
  269. }
  270. }
  271. private void measureView(View child) {
  272. ViewGroup.LayoutParams p = child.getLayoutParams();
  273. if (p == null) {
  274. p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
  275. }
  276. int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
  277. int lpHeight = p.height;
  278. int childHeightSpec;
  279. if (lpHeight > 0) {
  280. childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
  281. } else {
  282. childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
  283. }
  284. child.measure(childWidthSpec, childHeightSpec);
  285. }
  286. @SuppressWarnings("deprecation")
  287. public void setAdapter(BaseAdapter adapter) {
  288. lastUpdatedTextView.setText("最近更新:" + new Date().toLocaleString());
  289. super.setAdapter(adapter);
  290. }
  291. }

在 CustomListView 中有2个回调接口,OnRefreshListener 和 OnLoadListener ,分别对应 下拉和点击加载更多 时候的回调函数。在下拉刷新完成之后要调用 mListView.onRefreshComplete(); 来隐藏掉 头部,调用 mListView.onLoadComplete(); 隐藏掉 底部的加载view。

header.xml

[html] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- ListView的头部 -->
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="fill_parent"
  5. android:layout_height="wrap_content" >
  6. <!-- 内容 -->
  7. <RelativeLayout
  8. android:id="@+id/head_contentLayout"
  9. android:layout_width="fill_parent"
  10. android:layout_height="wrap_content"
  11. android:paddingLeft="30dp" >
  12. <!-- 箭头图像、进度条 -->
  13. <FrameLayout
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:layout_alignParentLeft="true"
  17. android:layout_centerVertical="true" >
  18. <!-- 箭头 -->
  19. <ImageView
  20. android:id="@+id/head_arrowImageView"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:layout_gravity="center"
  24. android:contentDescription="@string/app_name"
  25. android:src="@drawable/arrow" />
  26. <!-- 进度条 -->
  27. <ProgressBar
  28. android:id="@+id/head_progressBar"
  29. style="?android:attr/progressBarStyleSmall"
  30. android:layout_width="wrap_content"
  31. android:layout_height="wrap_content"
  32. android:layout_gravity="center"
  33. android:indeterminateDrawable="@drawable/progressbar_bg"
  34. android:visibility="gone" />
  35. </FrameLayout>
  36. <!-- 提示、最近更新 -->
  37. <LinearLayout
  38. android:layout_width="wrap_content"
  39. android:layout_height="wrap_content"
  40. android:layout_centerHorizontal="true"
  41. android:gravity="center_horizontal"
  42. android:orientation="vertical" >
  43. <!-- 提示 -->
  44. <TextView
  45. android:id="@+id/head_tipsTextView"
  46. android:layout_width="wrap_content"
  47. android:layout_height="wrap_content"
  48. android:text="@string/pull_to_refresh_pull_label"
  49. android:textColor="@color/pull_refresh_textview"
  50. android:textSize="20sp" />
  51. <!-- 最近更新 -->
  52. <TextView
  53. android:id="@+id/head_lastUpdatedTextView"
  54. android:layout_width="wrap_content"
  55. android:layout_height="wrap_content"
  56. android:text="@string/pull_to_refresh_refresh_lasttime"
  57. android:textColor="@color/gold"
  58. android:textSize="10sp" />
  59. </LinearLayout>
  60. </RelativeLayout>
  61. </LinearLayout>

listfooter_more.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="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:gravity="center_horizontal"
  6. android:orientation="horizontal"
  7. android:padding="15dp"
  8. >
  9. <ProgressBar
  10. android:id="@+id/pull_to_refresh_progress"
  11. style="@android:style/Widget.ProgressBar.Small.Inverse"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:gravity="center"
  15. android:indeterminate="true"
  16. android:visibility="gone" >
  17. </ProgressBar>
  18. <TextView
  19. android:id="@+id/load_more"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:layout_marginLeft="10.0dp"
  23. android:gravity="center"
  24. android:text="@string/more_data"
  25. android:textColor="@color/black" >
  26. </TextView>
  27. </LinearLayout>

MainActivity.java

[java] view plaincopy

  1. package com.example.uitest;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import android.app.Activity;
  5. import android.content.Context;
  6. import android.graphics.BitmapFactory;
  7. import android.os.Bundle;
  8. import android.os.Handler;
  9. import android.util.Log;
  10. import android.view.LayoutInflater;
  11. import android.view.Menu;
  12. import android.view.View;
  13. import android.view.ViewGroup;
  14. import android.widget.AdapterView;
  15. import android.widget.AdapterView.OnItemClickListener;
  16. import android.widget.BaseAdapter;
  17. import android.widget.ImageView;
  18. import android.widget.TextView;
  19. import com.example.uitest.model.AppInfo;
  20. import com.example.uitest.view.CustomListView;
  21. import com.example.uitest.view.CustomListView.OnLoadListener;
  22. import com.example.uitest.view.CustomListView.OnRefreshListener;
  23. public class MainActivity extends Activity {
  24. private static final String TAG = MainActivity.class.getSimpleName();
  25. private static final int LOAD_DATA_FINISH = 10;
  26. private static final int REFRESH_DATA_FINISH = 11;
  27. private List<AppInfo> mList = new ArrayList<AppInfo>();
  28. private CustomListAdapter mAdapter;
  29. private CustomListView mListView;
  30. private int count = 10;
  31. private Handler handler = new Handler(){
  32. public void handleMessage(android.os.Message msg) {
  33. switch (msg.what) {
  34. case REFRESH_DATA_FINISH:
  35. if(mAdapter!=null){
  36. mAdapter.notifyDataSetChanged();
  37. }
  38. mListView.onRefreshComplete();  //下拉刷新完成
  39. break;
  40. case LOAD_DATA_FINISH:
  41. if(mAdapter!=null){
  42. mAdapter.notifyDataSetChanged();
  43. }
  44. mListView.onLoadComplete(); //加载更多完成
  45. break;
  46. default:
  47. break;
  48. }
  49. };
  50. };
  51. @Override
  52. protected void onCreate(Bundle savedInstanceState) {
  53. super.onCreate(savedInstanceState);
  54. setContentView(R.layout.activity_main);
  55. buildAppData();
  56. mAdapter = new CustomListAdapter(this);
  57. mListView = (CustomListView) findViewById(R.id.mListView);
  58. mListView.setAdapter(mAdapter);
  59. mListView.setonRefreshListener(new OnRefreshListener() {
  60. @Override
  61. public void onRefresh() {
  62. //TODO 下拉刷新
  63. Log.e(TAG, "onRefresh");
  64. loadData(0);
  65. }
  66. });
  67. mListView.setonLoadListener(new OnLoadListener() {
  68. @Override
  69. public void onLoad() {
  70. //TODO 加载更多
  71. Log.e(TAG, "onLoad");
  72. loadData(1);
  73. }
  74. });
  75. mListView.setOnItemClickListener(new OnItemClickListener() {
  76. @Override
  77. public void onItemClick(AdapterView<?> parent, View view,
  78. int position, long id) {
  79. Log.e(TAG, "click position:" + position);
  80. }
  81. });
  82. }
  83. public void loadData(final int type){
  84. new Thread(){
  85. @Override
  86. public void run() {
  87. for(int i=count;i<count+10;i++){
  88. AppInfo ai = new AppInfo();
  89. ai.setAppIcon(BitmapFactory.decodeResource(getResources(),
  90. R.drawable.ic_launcher));
  91. ai.setAppName("应用Demo_" + i);
  92. ai.setAppVer("版本: " + (i % 10 + 1) + "." + (i % 8 + 2) + "."
  93. + (i % 6 + 3));
  94. ai.setAppSize("大小: " + i * 10 + "MB");
  95. mList.add(ai);
  96. }
  97. count += 10;
  98. try {
  99. Thread.sleep(300);
  100. } catch (InterruptedException e) {
  101. e.printStackTrace();
  102. }
  103. if(type==0){    //下拉刷新
  104. //                  Collections.reverse(mList); //逆序
  105. handler.sendEmptyMessage(REFRESH_DATA_FINISH);
  106. }else if(type==1){
  107. handler.sendEmptyMessage(LOAD_DATA_FINISH);
  108. }
  109. }
  110. }.start();
  111. }
  112. /**
  113. * 初始化应用数据
  114. */
  115. private void buildAppData() {
  116. for (int i = 0; i < 10; i++) {
  117. AppInfo ai = new AppInfo();
  118. ai.setAppIcon(BitmapFactory.decodeResource(getResources(),
  119. R.drawable.ic_launcher));
  120. ai.setAppName("应用Demo_" + i);
  121. ai.setAppVer("版本: " + (i % 10 + 1) + "." + (i % 8 + 2) + "."
  122. + (i % 6 + 3));
  123. ai.setAppSize("大小: " + i * 10 + "MB");
  124. mList.add(ai);
  125. }
  126. }
  127. @Override
  128. public boolean onCreateOptionsMenu(Menu menu) {
  129. // Inflate the menu; this adds items to the action bar if it is present.
  130. getMenuInflater().inflate(R.menu.main, menu);
  131. return true;
  132. }
  133. public class CustomListAdapter extends BaseAdapter {
  134. private LayoutInflater mInflater;
  135. public CustomListAdapter(Context context) {
  136. mInflater = LayoutInflater.from(context);
  137. }
  138. @Override
  139. public int getCount() {
  140. return mList.size();
  141. }
  142. @Override
  143. public Object getItem(int arg0) {
  144. return mList.get(arg0);
  145. }
  146. @Override
  147. public long getItemId(int position) {
  148. return position;
  149. }
  150. @Override
  151. public View getView(int position, View convertView, ViewGroup parent) {
  152. if (getCount() == 0) {
  153. return null;
  154. }
  155. ViewHolder holder = null;
  156. if (convertView == null) {
  157. convertView = mInflater.inflate(R.layout.list_item, null);
  158. holder = new ViewHolder();
  159. holder.ivImage = (ImageView) convertView
  160. .findViewById(R.id.ivIcon);
  161. holder.tvName = (TextView) convertView
  162. .findViewById(R.id.tvName);
  163. holder.tvVer = (TextView) convertView.findViewById(R.id.tvVer);
  164. holder.tvSize = (TextView) convertView
  165. .findViewById(R.id.tvSize);
  166. convertView.setTag(holder);
  167. } else {
  168. holder = (ViewHolder) convertView.getTag();
  169. }
  170. AppInfo ai = mList.get(position);
  171. holder.ivImage.setImageBitmap(ai.getAppIcon());
  172. holder.tvName.setText(ai.getAppName());
  173. holder.tvVer.setText(ai.getAppVer());
  174. holder.tvSize.setText(ai.getAppSize());
  175. return convertView;
  176. }
  177. }
  178. public static class ViewHolder {
  179. private ImageView ivImage;
  180. private TextView tvName;
  181. private TextView tvVer;
  182. private TextView tvSize;
  183. }
  184. }

list_item.xml

[html] view plaincopy

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <RelativeLayout
    3. xmlns:android="http://schemas.android.com/apk/res/android"
    4. android:layout_width="match_parent"
    5. android:layout_height="wrap_content" >
    6. <ImageView
    7. android:id="@+id/ivIcon"
    8. android:layout_width="wrap_content"
    9. android:layout_height="wrap_content"
    10. android:contentDescription="@string/image_desc"
    11. android:src="@drawable/ic_launcher" />
    12. <LinearLayout
    13. android:id="@+id/appInfo"
    14. android:layout_width="match_parent"
    15. android:layout_height="wrap_content"
    16. android:layout_marginLeft="5dip"
    17. android:layout_toRightOf="@id/ivIcon"
    18. android:orientation="vertical" >
    19. <TextView
    20. android:id="@+id/tvName"
    21. android:layout_width="wrap_content"
    22. android:layout_height="wrap_content"
    23. android:text="@string/name"
    24. android:textColor="#000000"
    25. android:textSize="16sp" />
    26. <TextView
    27. android:id="@+id/tvVer"
    28. android:layout_width="wrap_content"
    29. android:layout_height="wrap_content"
    30. android:text="@string/ver"
    31. android:textColor="#666666"
    32. android:textSize="13sp" />
    33. <TextView
    34. android:id="@+id/tvSize"
    35. android:layout_width="wrap_content"
    36. android:layout_height="wrap_content"
    37. android:text="@string/size"
    38. android:textColor="#666666"
    39. android:textSize="13sp" />
    40. </LinearLayout>
    41. <Button
    42. android:id="@+id/btnClick"
    43. android:layout_width="80dip"
    44. android:layout_height="wrap_content"
    45. android:layout_alignParentRight="true"
    46. android:layout_centerVertical="true"
    47. android:focusable="false"
    48. android:text="@string/mgr"
    49. android:textColor="#000000"
    50. android:textSize="16sp" />
    51. </RelativeLayout>
时间: 2024-12-04 11:55:05

Android ListView 下拉刷新 点击加载更多的相关文章

最新Android ListView 下拉刷新 上滑加载

开发项目过程中基本都会用到listView的下拉刷新和上滑加载更多,之前大家最常用的应该是pull to refresh或它的变种版吧,google官方在最新的android.support.v4包中增加了一个新类SwipeRefreshLayout,地址 这个类的作用就是提供官方的下拉刷新,并且效果相当不错,而上拉加载更多则用我们自定义的listview,也是相当简单. 下拉刷新 简单的介绍下: 首先它是一个viewgroup,但是它只允许有一个子控件,子控件能是任何view,使用的时候,所在

十分钟实现ListView下拉刷新上滑加载更多

说到ListView下拉刷新几乎每个APP都会用到,所以ListView下拉刷新是很重要的,就像ListView优化一样是你必会的东西. ListView实现下拉刷新如果我们开发人员自己编写相对来说比较费事的,当我们使用第三方库之后我们再来开发这个功能就会省事很多.相比与自己实现可以少编写不少代码,Android-PullToRefresh库可以轻松实现ListView的下拉刷新功能. 要使用Android—PullToRefesh库对ListView实现下拉刷新要经过以下几个步骤: 1.下载A

Android下拉刷新库,利用viewdraghelper实现,集成了下拉刷新,底部加载更多,数据初始加载显示loading等功能

项目Github地址:https://github.com/sddyljsx/pulltorefresh Android下拉刷新库,利用viewdraghelper实现. 集成了下拉刷新,底部加载更多,以及刚进入加载数据的loadview.包括了listview与gridview的改写. 效果1: 效果2: 效果3: 效果4: 效果5: 使用说明: imageList=(ListView)findViewById(R.id.image_list); imageAdapter=new ImageA

IOS学习之UiTableView下拉刷新与自动加载更多,百年不变的效果

IOS学习之UiTableView下拉刷新与自动加载更多,百年不变的效果(五) 五一劳动节马上来临,小伙伴有妹有很激动哟,首先祝天下所有的程序猿节日快乐!这个五一对于我来说有点不一样,我的人生从这个五一就转弯了,爱情长跑8年的我结婚了,一会支付宝账号我会公布出去,请自觉打款!谢谢合作. 灯光闪起来: 舞蹈跳起来: 歌曲唱起来: -------------------------------------------------------------------------------------

支持下拉刷新和上划加载更多的自定义RecyclerView(仿XListView效果)

首先看效果 下拉刷新:        上划加载        在项目更新的过程中,遇到了一个将XListView换成recyclerView的需求,而且更换完之后大体效果不能变,但是对于下拉刷新这样的效果,谷歌给出的解决方案是把RecyclerView放在一个SwipeRefreshLayout中,但是这样其实是拉下一个小圆形控件实现的,和XListView的header效果不同.在网上找了很多的别人代码,都没有实现我想要的效果,于是自己动手写了一个. 具体实现的效果有以下几条 下拉刷新功能:

Android第二十三期 - 256k的ListView下拉刷新和滚动加载数据

代码已经

Android 自定义 ListView 上下拉动&ldquo;刷新最新&rdquo;和&ldquo;加载更多&rdquo;歌曲列表

本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码太多,点击此处下载,自己调试一下. 下载 Demo 环境 Windows 2008 R2 64 位 Eclipse ADT V22.6.2,Android 4.4.3 SAMSUNG GT-I9008L,Android OS 2.2.2 测试数据 本演示的歌曲信息,共有 20 条,包括歌手名.歌曲名.时长.缩

Android listview下拉刷新 上拉加载

转载自:http://blog.csdn.net/bboyfeiyu Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能 http://blog.csdn.net/guolin_blog/article/details/9255575 打造通用的Android下拉刷新组件(适用于ListView.GridView等各类View)  http://blog.csdn.net/bboyfeiyu/article/details/39718861 Android打造(ListView.Gr

android ListView下拉刷新之功能实现

首先要知道刷新有三个状态, 1是下拉中 2是松开刷新 3是正在刷新 还有一个非常重要的是回调接口,这个接口是正在刷新的时候外界需要做的事. 然后外界再把状态重置. 回调接口需要三个属性, private OnRefLisner listener; public void setOnRefLisner(OnRefLisner listener){        this.listener = listener;    } //回调接口    public interface OnRefLisner