Android ListView实现下拉加载功能

本文实例为大家分享了ListView下拉加载展示的具体代码,供大家参考,具体内容如下

1、MyListView.Java

public class MyListView extends ListView implements OnScrollListener { 

 private final static int RELEASE_To_REFRESH = 0;// 下拉过程的状态值
 private final static int PULL_To_REFRESH = 1; // 从下拉返回到不刷新的状态值
 private final static int REFRESHING = 2;// 正在刷新的状态值
 private final static int DONE = 3;
 private final static int LOADING = 4; 

 // 实际的padding的距离与界面上偏移距离的比例
 private final static int RATIO = 3;
 private LayoutInflater inflater; 

 // ListView头部下拉刷新的布局
 private LinearLayout headerView;
 private TextView lvHeaderTipsTv;
 private TextView lvHeaderLastUpdatedTv;
 private ImageView lvHeaderArrowIv;
 private ProgressBar lvHeaderProgressBar; 

 // 定义头部下拉刷新的布局的高度
 private int headerContentHeight; 

 private RotateAnimation animation;
 private RotateAnimation reverseAnimation; 

 private int startY;
 private int state;
 private boolean isBack; 

 // 用于保证startY的值在一个完整的touch事件中只被记录一次
 private boolean isRecored; 

 private OnRefreshListener refreshListener; 

 private boolean isRefreshable; 

 public MyListView(Context context) {
  super(context);
  init(context);
 } 

 public MyListView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init(context);
 } 

 private void init(Context context) {
  inflater = LayoutInflater.from(context);
  headerView = (LinearLayout) inflater.inflate(R.layout.lv_header, null);
  lvHeaderTipsTv = (TextView) headerView
    .findViewById(R.id.lvHeaderTipsTv);
  lvHeaderLastUpdatedTv = (TextView) headerView
    .findViewById(R.id.lvHeaderLastUpdatedTv); 

  lvHeaderArrowIv = (ImageView) headerView
    .findViewById(R.id.lvHeaderArrowIv);
  // 设置下拉刷新图标的最小高度和宽度
  lvHeaderArrowIv.setMinimumWidth(70);
  lvHeaderArrowIv.setMinimumHeight(50); 

  lvHeaderProgressBar = (ProgressBar) headerView
    .findViewById(R.id.lvHeaderProgressBar);
  measureView(headerView);
  headerContentHeight = headerView.getMeasuredHeight();
  // 设置内边距,正好距离顶部为一个负的整个布局的高度,正好把头部隐藏
  headerView.setPadding(0, -1 * headerContentHeight, 0, 0);
  // 重绘一下
  headerView.invalidate();
  // 将下拉刷新的布局加入ListView的顶部
  addHeaderView(headerView, null, false);
  // 设置滚动监听事件
  setOnScrollListener(this); 

  // 设置旋转动画事件
  animation = new RotateAnimation(0, -180,
    RotateAnimation.RELATIVE_TO_SELF, 0.5f,
    RotateAnimation.RELATIVE_TO_SELF, 0.5f);
  animation.setInterpolator(new LinearInterpolator());
  animation.setDuration(250);
  animation.setFillAfter(true); 

  reverseAnimation = new RotateAnimation(-180, 0,
    RotateAnimation.RELATIVE_TO_SELF, 0.5f,
    RotateAnimation.RELATIVE_TO_SELF, 0.5f);
  reverseAnimation.setInterpolator(new LinearInterpolator());
  reverseAnimation.setDuration(200);
  reverseAnimation.setFillAfter(true); 

  // 一开始的状态就是下拉刷新完的状态,所以为DONE
  state = DONE;
  // 是否正在刷新
  isRefreshable = false;
 } 

 @Override
 public void onScrollStateChanged(AbsListView view, int scrollState) { 

 } 

 @Override
 public void onScroll(AbsListView view, int firstVisibleItem,
   int visibleItemCount, int totalItemCount) {
  if (firstVisibleItem == 0) {
   isRefreshable = true;
  } else {
   isRefreshable = false;
  }
 } 

 @Override
 public boolean onTouchEvent(MotionEvent ev) {
  if (isRefreshable) {
   switch (ev.getAction()) {
   case MotionEvent.ACTION_DOWN:
    if (!isRecored) {
     isRecored = true;
     startY = (int) ev.getY();// 手指按下时记录当前位置
    }
    break;
   case MotionEvent.ACTION_UP:
    if (state != REFRESHING && state != LOADING) {
     if (state == PULL_To_REFRESH) {
      state = DONE;
      changeHeaderViewByState();
     }
     if (state == RELEASE_To_REFRESH) {
      state = REFRESHING;
      changeHeaderViewByState();
      onLvRefresh();
     }
    }
    isRecored = false;
    isBack = false; 

    break; 

   case MotionEvent.ACTION_MOVE:
    int tempY = (int) ev.getY();
    if (!isRecored) {
     isRecored = true;
     startY = tempY;
    }
    if (state != REFRESHING && isRecored && state != LOADING) {
     // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
     // 可以松手去刷新了
     if (state == RELEASE_To_REFRESH) {
      setSelection(0);
      // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
      if (((tempY - startY) / RATIO < headerContentHeight)// 由松开刷新状态转变到下拉刷新状态
        && (tempY - startY) > 0) {
       state = PULL_To_REFRESH;
       changeHeaderViewByState();
      }
      // 一下子推到顶了
      else if (tempY - startY <= 0) {// 由松开刷新状态转变到done状态
       state = DONE;
       changeHeaderViewByState();
      }
     }
     // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
     if (state == PULL_To_REFRESH) {
      setSelection(0);
      // 下拉到可以进入RELEASE_TO_REFRESH的状态
      if ((tempY - startY) / RATIO >= headerContentHeight) {// 由done或者下拉刷新状态转变到松开刷新
       state = RELEASE_To_REFRESH;
       isBack = true;
       changeHeaderViewByState();
      }
      // 上推到顶了
      else if (tempY - startY <= 0) {// 由DOne或者下拉刷新状态转变到done状态
       state = DONE;
       changeHeaderViewByState();
      }
     }
     // done状态下
     if (state == DONE) {
      if (tempY - startY > 0) {
       state = PULL_To_REFRESH;
       changeHeaderViewByState();
      }
     }
     // 更新headView的size
     if (state == PULL_To_REFRESH) {
      headerView.setPadding(0, -1 * headerContentHeight
        + (tempY - startY) / RATIO, 0, 0); 

     }
     // 更新headView的paddingTop
     if (state == RELEASE_To_REFRESH) {
      headerView.setPadding(0, (tempY - startY) / RATIO
        - headerContentHeight, 0, 0);
     } 

    }
    break; 

   default:
    break;
   }
  }
  return super.onTouchEvent(ev);
 } 

 // 当状态改变时候,调用该方法,以更新界面
 private void changeHeaderViewByState() {
  switch (state) {
  case RELEASE_To_REFRESH:
   lvHeaderArrowIv.setVisibility(View.VISIBLE);
   lvHeaderProgressBar.setVisibility(View.GONE);
   lvHeaderTipsTv.setVisibility(View.VISIBLE);
   lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE); 

   lvHeaderArrowIv.clearAnimation();// 清除动画
   lvHeaderArrowIv.startAnimation(animation);// 开始动画效果 

   lvHeaderTipsTv.setText("松开刷新");
   break;
  case PULL_To_REFRESH:
   lvHeaderProgressBar.setVisibility(View.GONE);
   lvHeaderTipsTv.setVisibility(View.VISIBLE);
   lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
   lvHeaderArrowIv.clearAnimation();
   lvHeaderArrowIv.setVisibility(View.VISIBLE);
   // 是由RELEASE_To_REFRESH状态转变来的
   if (isBack) {
    isBack = false;
    lvHeaderArrowIv.clearAnimation();
    lvHeaderArrowIv.startAnimation(reverseAnimation); 

    lvHeaderTipsTv.setText("下拉刷新");
   } else {
    lvHeaderTipsTv.setText("下拉刷新");
   }
   break; 

  case REFRESHING: 

   headerView.setPadding(0, 0, 0, 0); 

   lvHeaderProgressBar.setVisibility(View.VISIBLE);
   lvHeaderArrowIv.clearAnimation();
   lvHeaderArrowIv.setVisibility(View.GONE);
   lvHeaderTipsTv.setText("正在刷新...");
   lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
   break;
  case DONE:
   headerView.setPadding(0, -1 * headerContentHeight, 0, 0); 

   lvHeaderProgressBar.setVisibility(View.GONE);
   lvHeaderArrowIv.clearAnimation();
   lvHeaderArrowIv.setImageResource(R.drawable.arrow);
   lvHeaderTipsTv.setText("下拉刷新");
   lvHeaderLastUpdatedTv.setVisibility(View.VISIBLE);
   break;
  }
 } 

 // 此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headView的width以及height
 private void measureView(View child) {
  ViewGroup.LayoutParams params = child.getLayoutParams();
  if (params == null) {
   params = new ViewGroup.LayoutParams(
     ViewGroup.LayoutParams.FILL_PARENT,
     ViewGroup.LayoutParams.WRAP_CONTENT);
  }
  int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0,
    params.width);
  int lpHeight = params.height;
  int childHeightSpec;
  if (lpHeight > 0) {
   childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
     MeasureSpec.EXACTLY);
  } else {
   childHeightSpec = MeasureSpec.makeMeasureSpec(0,
     MeasureSpec.UNSPECIFIED);
  }
  child.measure(childWidthSpec, childHeightSpec);
 } 

 public void setonRefreshListener(OnRefreshListener refreshListener) {
  this.refreshListener = refreshListener;
  isRefreshable = true;
 } 

 public interface OnRefreshListener {
  public void onRefresh();
 } 

 public void onRefreshComplete() {
  state = DONE;
  lvHeaderLastUpdatedTv.setText("最近更新:" + new Date().toLocaleString());
  changeHeaderViewByState();
 } 

 private void onLvRefresh() {
  if (refreshListener != null) {
   refreshListener.onRefresh();
  }
 } 

 public void setAdapter(LvAdapter adapter) {
  lvHeaderLastUpdatedTv.setText("最近更新:" + new Date().toLocaleString());
  super.setAdapter(adapter);
 } 

}

2、MainActivity.java

public class MainActivity extends Activity {
 private List<String> list;
 private MyListView lv;
 private LvAdapter adapter; 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  lv = (MyListView) findViewById(R.id.lv);
  list = new ArrayList<String>();
  list.add("loonggg");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  list.add("我们都是开发者");
  adapter = new LvAdapter(list, this);
  lv.setAdapter(adapter); 

  lv.setonRefreshListener(new OnRefreshListener() { 

   @Override
   public void onRefresh() {
    new AsyncTask<Void, Void, Void>() {
     protected Void doInBackground(Void... params) {
      try {
       Thread.sleep(1000);
      } catch (Exception e) {
       e.printStackTrace();
      }
      list.add("刷新后添加的内容");
      return null;
     } 

     @Override
     protected void onPostExecute(Void result) {
      adapter.notifyDataSetChanged();
      lv.onRefreshComplete();
     }
    }.execute(null, null, null);
   }
  });
 }
}

3、LvAdapter
public class LvAdapter extends BaseAdapter { 
    private List<String> list; 
    private Context context; 
 
    public LvAdapter(List<String> list, Context context) { 
        this.list = list; 
        this.context = context; 
    } 
 
    @Override 
    public int getCount() { 
        return list.size(); 
    } 
 
    @Override 
    public Object getItem(int position) { 
        return list.get(position); 
    } 
 
    @Override 
    public long getItemId(int position) { 
        return position; 
    } 
 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
        TextView tv = new TextView(context.getApplicationContext()); 
        tv.setText(list.get(position)); 
        return tv; 
    } 
 
}

4、lv_header.xml
[html] view plain copy
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:background="#000000" > 
 
    <!-- 内容 --> 
 
    <RelativeLayout 
        android:id="@+id/head_contentLayout" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:paddingLeft="30dp" > 
 
        <!-- 箭头图像、进度条 --> 
 
        <FrameLayout 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:layout_alignParentLeft="true" 
            android:layout_centerVertical="true" > 
 
            <!-- 箭头 --> 
 
            <ImageView 
                android:id="@+id/lvHeaderArrowIv" 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:layout_gravity="center" 
                android:src="@drawable/arrow" /> 
 
            <!-- 进度条 --> 
 
            <ProgressBar 
                android:id="@+id/lvHeaderProgressBar" 
                style="?android:attr/progressBarStyleSmall" 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:layout_gravity="center" 
                android:visibility="gone" /> 
        </FrameLayout> 
 
        <!-- 提示、最近更新 --> 
 
        <LinearLayout 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:layout_centerHorizontal="true" 
            android:gravity="center_horizontal" 
            android:orientation="vertical" > 
 
            <!-- 提示 --> 
 
            <TextView 
                android:id="@+id/lvHeaderTipsTv" 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="下拉刷新" 
                android:textColor="#fff" 
                android:textSize="20sp" /> 
 
            <!-- 最近更新 --> 
 
            <TextView 
                android:id="@+id/lvHeaderLastUpdatedTv" 
                android:layout_width="wrap_content" 
                android:layout_height="wrap_content" 
                android:text="上次更新" 
                android:textColor="#333" 
                android:textSize="10sp" /> 
        </LinearLayout> 
    </RelativeLayout> 
 
</LinearLayout>

5、main.xml
[html] view plain copy
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="#000000" 
    android:orientation="vertical" > 
 
    <net.loonggg.listview.MyListView 
        android:id="@+id/lv" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" /> 
 
</LinearLayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android仿XListView支持下拉刷新和上划加载更多的自定义RecyclerView

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

  • Android ListView实现上拉加载更多和下拉刷新功能

    本文实例为大家介绍了Android ListView下拉刷新功能的实现方法和功能,供大家参考,具体内容如下 1.ListView优化方式 界面缓存:ViewHolder+convertView 分页加载:上拉刷新 图片缓存 快速滑动ListView禁止刷新 2.效果 3.上拉加载更多原理及实现 当我们手指滑动到listview最后位置的时候,我们触发加载数据的方法.这触发之前我们需要做一些工作,包括: 如何判断滑动到最后? 如何避免重复加载数据? 加载之后如何刷新界面? 1).界面实现AbsLi

  • Android XListView下拉刷新和上拉加载更多

    市面上有好多的类比ListView刷新数据的开源框架,如:v4包自带的SwipeRefreshLayout ,以及集ListView.GridView甚至WebView于一身的Pulltorefresh等等.前述的两个开源框架目前使用也算频繁.有兴趣的读者可以自行搜索,当然有时间一定回来对所有的使用方式做一个汇总和比较.今天介绍的这款框架,专门针对ListView做下拉刷新与上拉加载的,如果单单是ListView就显得更加简单方便易于理解. 1.首先引入xListView_lib库到自己的Dem

  • Android程序开发之Listview下拉刷新上拉(滑动分页)加载更多

    最近做的类似于微博的项目中,有个Android功能要使用到listview的向下拉刷新来刷新最新消息,向上拉刷新(滑动分页)来加载更多. 新浪微博就是使用这种方式的典型. 当用户从网络上读取微博的时候,如果一下子全部加载用户未读的微博这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容.这时候,我们就需要用到另一个功能,那就是listview的分页了,其实这个分页可以做成客户端的分页,也可以做成服务器端的分页(点击加载时,从服务器对应的加载第N页就好了!!!).通过分

  • ListView实现下拉刷新加载更多的实例代码(直接拿来用)

    ListView Api bixu 好好看看 mNewsAdapter.notifyDataSetChanged();//刷新ListView 自定义的RefreashListView package com.itguang.dell_pc.myapplication.view; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import and

  • Android实现上拉加载更多以及下拉刷新功能(ListView)

    首先为大家介绍Andorid5.0原生下拉刷新简单实现. 先上效果图: 相对于上一个19.1.0版本中的横条效果好看了很多.使用起来也很简单. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" and

  • Android ListView实现上拉加载下拉刷新和滑动删除功能

    最近项目需要用到可以滑动删除并且带有上拉加载下拉刷新的Listview,查阅了一些资料,大多都是在SwipeMenuListView的基础上去添加头部和底部View,来扩展上拉加载和下拉刷新的功能,不过需要手动的去绘制UI及处理一些动画效果.用起来也不是特别方便.刚好项目中用到PulltorefreshLibrary库,就尝试着扩展了一个PullToRefreshSwipeMenuListView类来实现需求.先看一下效果: 实现步骤 一.组合Pulltorefresh与SwipeMenuLis

  • Android自定义listview布局实现上拉加载下拉刷新功能

    listview实现上拉加载以及下拉刷新的方式有很多.下面是我写的一种自定义的布局,复用性也比较的强.首先就是继承的listview的自定义view.   AutoListView.Java: package com.example.mic.testdemo.view; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.os.Bu

  • Android ListView下拉刷新上拉自动加载更多DEMO示例

    代码下载地址已经更新.因为代码很久没更新,已经很落伍了,建议大家使用RecyclerView实现. 参考项目: https://github.com/bingoogolapple/BGARefreshLayout-Android https://github.com/baoyongzhang/android-PullRefreshLayout 下拉刷新,Android中非常普遍的功能.为了方便便重写的ListView来实现下拉刷新,同时添加了上拉自动加载更多的功能.设计最初是参考开源中国的And

  • Android开发ListView中下拉刷新上拉加载及带列的横向滚动实现方法

    ListView 控件可使用四种不同视图显示项目.通过此控件,可将项目组成带有或不带有列标头的列,并显示伴随的图标和文本. 可使用 ListView 控件将称作 ListItem 对象的列表条目组织成下列四种不同的视图之一:1.大(标准)图标2.小图标3.列表4.报表 View 属性决定在列表中控件使用何种视图显示项目. 还可用 LabelWrap 属性控制列表中与项目关联的标签是否可换行显示.另外,还可管理列表中项目的排序方法和选定项目的外观. 相信有很人做的项目估计都用的到这个.就是List

随机推荐