Android ListView实现下拉加载功能

时间:2022-07-27
本文章向大家介绍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

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