很久没有更新了,老是忘记,哈哈。。。。。
那么今天就说一说listview的下拉刷新,通过这个我们可以学习到自定义view的一些属性,还有需要重写的一些方法,以及这些方法的作用。
虽然现在已经有下拉刷新的一些成熟的库了,例如PullToRefresh,有空你们可以去试一下,这个就比较简单了,只需调用里面的方法就可以实现下拉刷新的功能。
有兴趣的朋友可以学习一下。
个人觉得我这个其实有一点点的麻烦,但毕竟是自己刚开始的时候第一次写的一个自定义view,所以拿出来跟你们分享分享。下面就先贴出我的xml文件中的代码吧,必要的地方我会一些注释的。
这个是主页面的xml文件,是自定义listview的包名,
<com.example.reflashlistview.FlashListView
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
这个是listview的item的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="25dp"
android:textColor="#66ff0000"
android:text="文本一"
/>
</LinearLayout>
这个是头布局的文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true"
android:id="@+id/linear"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉可以刷新"
android:id="@+id/update"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/updatetime"
/>
</LinearLayout>
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/xia"
android:id="@+id/image"
android:layout_toLeftOf="@id/linear"
android:layout_marginRight="20dp"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progress"
style="?android:attr/progressBarStyleSmall"
android:visibility="gone"
android:layout_toLeftOf="@id/linear"
android:layout_marginRight="20dp"
/>
</RelativeLayout>
</LinearLayout>
好了,就到正文了,先贴出自定义view的代码
public class FlashListView extends ListView implements OnScrollListener{
View header;
int headerHeight;
int firstVisibleItem;//当前第一个可见的Item的位置
boolean isRemark;//标记,当前是在listview的最低端嗯下的
int startY;//摁下时的y值
int scrollState;//listview当前滚动的状态
int state;//当前的状态
final int NONE=0;//当前状态
final int PULL=1;//提示下拉状态
final int RELESE=2;//提示释放状态
final int REFLASHING=3;//刷新状态
IReflashListener listener;//刷新数据的接口
private TextView text;
private ProgressBar bar;
private ImageView image;
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
finish();
};
};
//这是要重写的构造方法
public FlashListView(Context context) {
super(context);
initView(context);
}
public FlashListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public FlashListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView(context);
}
//刷新完成后让头布局继续隐藏,并恢复到原来的状态
public void finish(){
if(state==REFLASHING){
state=PULL;
text.setText("下拉刷新");
bar.setVisibility(View.INVISIBLE);
image.setVisibility(View.VISIBLE);
header.setPadding(0, -headerHeight, 0, 0);
}
}
//初始化界面,添加顶部文件到listview中
private void initView(Context context){
LayoutInflater inflater = LayoutInflater.from(context);
header=inflater.inflate(R.layout.header, null);
text = (TextView) findViewById(R.id.update);
bar = (ProgressBar) findViewById(R.id.progress);
image = (ImageView) findViewById(R.id.image);
measureView(header);
headerHeight=header.getMeasuredHeight();
topPadding(-headerHeight);//高度是0
this.addHeaderView(header);
this.setOnScrollListener(this);
}
//通知父布局占用的宽和高
private void measureView(View view){
ViewGroup.LayoutParams p = view.getLayoutParams();
if(p==null){
p=new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int width=ViewGroup.getChildMeasureSpec(0, 0, p.width);
int height;
int tempHeight=p.height;
if(tempHeight>0){
height=MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
}else{
height=MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
view.measure(width, height);
}
//设置header布局的上边距
private void topPadding(int topPadding){
header.setPadding(header.getPaddingLeft(), topPadding, header.getPaddingRight(), header.getPaddingBottom());
header.invalidate();
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItem=firstVisibleItem;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
this.scrollState=scrollState;
}
//
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
if(firstVisibleItem==0){
isRemark=true;
startY=(int) ev.getY();
reflashViewByState();
}
break;
case MotionEvent.ACTION_MOVE:
onMove(ev);
reflashViewByState();
break;
case MotionEvent.ACTION_UP:
if(state==RELESE){
state=REFLASHING;
reflashViewByState();
//加载最新数据
}else if(state==PULL){
state=NONE;
isRemark=false;
reflashViewByState();
listener.onReflash();
}
break;
}
return super.onTouchEvent(ev);
}
//根据提示当前状态,改变界面显示
private void reflashViewByState(){
TextView textview = (TextView) header.findViewById(R.id.update);
ImageView image = (ImageView) header.findViewById(R.id.image);
ProgressBar progress = (ProgressBar) header.findViewById(R.id.progress);
RotateAnimation anim=new RotateAnimation(0, 180,
RotateAnimation.RELATIVE_TO_SELF,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
anim.setDuration(500);
anim.setFillAfter(true);
RotateAnimation anim1=new RotateAnimation(180, 0,
RotateAnimation.RELATIVE_TO_SELF,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
anim1.setDuration(500);
anim1.setFillAfter(true);
switch (state) {
case NONE:
image.clearAnimation();
topPadding(-headerHeight);
break;
case PULL:
image.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textview.setText("下拉可以刷新");
image.clearAnimation();
image.setAnimation(anim1);
break;
case RELESE:
image.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
textview.setText("松开可以刷新");
image.clearAnimation();
image.setAnimation(anim);
break;
case REFLASHING:
topPadding(50);
image.setVisibility(View.GONE);
progress.setVisibility(View.VISIBLE);
textview.setText("正在刷新...");
image.clearAnimation();
break;
}
}
//判断移动过程中的操作
private void onMove(MotionEvent ev){
if(!isRemark){
return;
}
int tempY=(int) ev.getY();
int space=tempY-startY;
int topPadding =space-headerHeight;
switch (state) {
case NONE:
if(space>0){
state=PULL;
reflashViewByState();
}
break;
case PULL:
topPadding(topPadding);
if(space>headerHeight+30&scrollState==SCROLL_STATE_TOUCH_SCROLL){
state=RELESE;
reflashViewByState();
}
break;
case RELESE:
topPadding(topPadding);
if(space<headerHeight+30){
state=PULL;
reflashViewByState();
}else if(space<=0){
state=NONE;
isRemark=false;
reflashViewByState();
}
break;
case REFLASHING:
topPadding(topPadding);
if(space<headerHeight+30){
state=PULL;
reflashViewByState();
}else if(space<=0){
state=NONE;
isRemark=false;
reflashViewByState();
}
break;
}
}
//获取完数据
public void reflashComplete(){
state=NONE;
isRemark=false;
reflashViewByState();
TextView updateTime = (TextView) header.findViewById(R.id.updatetime);
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日hh:mm:ss");
Date date = new Date(System.currentTimeMillis());
String time = format.format(date);
updateTime.setText(time);
}
public void setInterface(IReflashListener listener){
this.listener=listener;
}
//刷新数据接口
public interface IReflashListener{
public void onReflash();
}
}
然后是在主activity的操作,这里就比较简单了
public class MainActivity extends Activity implements IReflashListener{
private FlashListView ll;
private TextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = (FlashListView) findViewById(R.id.ll);
ll.setInterface(this);
ll.setAdapter(new MyAdapter());
}
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return 100;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if(convertView==null){
view=View.inflate(getApplicationContext(), R.layout.item, null);
}else{
view=convertView;
}
ImageView image = (ImageView) view.findViewById(R.id.image);
text = (TextView) view.findViewById(R.id.text);
text.setText("文本"+position);
image.setBackgroundResource(R.drawable.ic_launcher);
return view;
}
}
@Override
public void onReflash() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
ll.reflashComplete();
}
}, 2000);
//获取最新数据
//通知界面显示
//通知listview刷新数据完毕
ll.finish();
}
}
好了,到这里下拉刷新的操作就是完成了,我把全部的代码都贴在上面了,其中会有注释,希望你们能看明白。
因为曾经的我也为这个问题难为过,找了好多但都是一点,有的需要自己去尝试怎么跟自己写的融合,很麻烦。所以我明白自己找到的代码如果不能运行,还报一大堆的错误是多么的坑人,我会尽量的把所有的代码都给你们展示出来,希望你们看的高兴。
就到这里了。^-^ ^-^ ^-^