ListView下拉刷新效果
网上关于这个方面的文章已经很多了,为什么我还要发表这篇文章呢?原因很简单,我觉得可以可以用更加简洁的方法实现。话不多说,上代码。
CustomListView.java
package com.markslin.listviewtest;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
/**
* Created by MarksLin on 2015/5/7 0007.
*/
public class CustomListView extends ListView {
private int startY;
private boolean firstMeasured = true;
private View header;
private ProgressBar headerProgressBar;
private ImageView headerProgressImg;
private int headerHeight;
private OnRefreshListener listener;
public interface OnRefreshListener {
void onRefresh();
}
/**
* 接口回调,通知主程序加载数据
* @param listener
*/
public void setOnRefreshListener(OnRefreshListener listener){
this.listener=listener;
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
header = View.inflate(getContext(), R.layout.listview_header, null);
headerProgressBar = (ProgressBar) header.findViewById(R.id.header_progressBar);
headerProgressImg = (ImageView) header.findViewById(R.id.header_progressImg);
addHeaderView(header);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (firstMeasured) {//onLayout方法会被调用多次,因此要处理一下
firstMeasured = false;
intiView();
}
}
/**
* 初始化ListView的顶部布局
*/
private void intiView() {
headerHeight = header.getMeasuredHeight();
setHeaderTopPadding(-headerHeight);
}
/**
* 设置Header距顶部的padding
* @param padding
*/
private void setHeaderTopPadding(int padding) {
header.setPadding(header.getPaddingLeft(), padding, header.getPaddingRight(), header.getPaddingBottom());
}
/**
* 用与程序数据加载完毕后调用
*/
public void loadFinish() {
setHeaderTopPadding(-headerHeight);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (getFirstVisiblePosition() == 0) {
startY = (int) event.getY();
headerProgressImg.setVisibility(VISIBLE);
headerProgressBar.setVisibility(GONE);
}
break;
case MotionEvent.ACTION_MOVE:
int slideHeight = (int) event.getY() - startY;
if (slideHeight < 3 * headerHeight && slideHeight > headerHeight)
setHeaderTopPadding(-headerHeight + (int) event.getY() - startY);
headerProgressImg.setRotation(120 * ((int) event.getY() - startY) / headerHeight);
break;
case MotionEvent.ACTION_UP:
if (((int) event.getY() - startY) > headerHeight) {
headerProgressImg.setVisibility(GONE);
headerProgressBar.setVisibility(VISIBLE);
setHeaderTopPadding(0);
listener.onRefresh();
} else
setHeaderTopPadding(-header.getMeasuredHeight());
default:
break;
}
return super.onTouchEvent(event);
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.markslin.listviewtest.CustomListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listView"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
listview_header.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:layout_width="72dp"
android:layout_height="72dp"
android:id="@+id/header_progressBar"
android:padding="@dimen/activity_horizontal_margin"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:indeterminateDrawable="@drawable/loading"
android:visibility="gone"/>
<ImageView
android:layout_width="72dp"
android:layout_height="72dp"
android:id="@+id/header_progressImg"
android:padding="@dimen/activity_horizontal_margin"
android:src="@drawable/loading_img"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
MainActivity.java
package com.markslin.listviewtest;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements CustomListView.OnRefreshListener{
private CustomListView listView;
private List<String> strings=new ArrayList<>();
private ListViewAdapter adapter;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView= (CustomListView) findViewById(R.id.listView);
for (int i=0;i<30;i++)
strings.add("Hello");
adapter=new ListViewAdapter(strings);
listView.setAdapter(adapter);
listView.setOnRefreshListener(this);
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==1)
listView.loadFinish();
}
};
}
@Override
public void onRefresh() {
handler.sendEmptyMessageDelayed(1,3000);
}
}
ListViewAdapter.java
package com.markslin.listviewtest;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by MarksLin on 2015/5/7 0007.
*/
public class ListViewAdapter extends BaseAdapter{
private List<String> strings=new ArrayList<>();
public ListViewAdapter(List<String> strings) {
this.strings = strings;
}
@Override
public int getCount() {
return strings.size();
}
@Override
public Object getItem(int position) {
return strings.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view=new TextView(parent.getContext());
view.setHeight(75);
view.setText(strings.get(position));
return view;
}
}
还是总结一下吧,贴上这么多代码,其实最重要的是第一个自定义View(CustomListView),初始化的时候要放在onLayout方法里,不然得不到高度的值,网上好多是自己写的测量方法,我觉得没这个必要去再测量一边,在onLayout方法调用的时候系统已经测量过了。代码写的不好,请不要见笑。