您的位置:首页 > 移动开发 > Android开发

Android自定义控件实战——仿新浪微博、QQ好友动态滑到底部自动加载

2014-08-31 20:57 489 查看
转载请声明出处/article/7618175.html

前一篇已经把下拉刷新和上拉加载集成到一块了并且已经对所有View通用了,但是有时候需要的加载方式不是上拉,而是像新浪微博加载评论或QQ好友动态滑到ListView的底部时就自动加载了。所以在这篇文章里再介绍这种自动加载的实现,当然了,这个功能只针对ListView。如果仅仅是实现这样的自动加载,那就太简单了,也就判断是否滚动到底部而已,代码量很少,所以还加了下拉刷新,但在这里这两个功能是独立的,自动加载只是针对ListView进行的修改。

效果图如下:



下拉刷新的原理就不讲了,可以去看 Android通用版下拉刷新上拉加载控件,实现自动加载的思路就是:

在ListView后面增加一个FooterView,时刻监听ListView的滑动状态,当FooterView被滑到可见时,执行自动加载操作。

但是这里需要注意的是手动滑到底和自由滚到底时的区别:

1、使劲滑的时候自由滚动在底部时会显示自动加载并执行加载回调

2、当用手慢慢滑动到底时,如果不松手,不会自动加载。

所以,基于这两个考虑,自然而然就需要覆写View的两个方法:onScrollChanged和onTouchEvent。

接下来就可以看代码了:

package com.jingchen.autoload;

import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

/**
* 如果不需要下拉刷新直接在canPullDown中返回false,这里的自动加载和下拉刷新没有冲突,通过增加在尾部的footerview实现自动加载,
* 所以在使用中不要再动footerview了
*
* @author chenjing
*
*/
public class PullableListView extends ListView implements Pullable
{
public static final int INIT = 0;
public static final int LOADING = 1;
private OnLoadListener mOnLoadListener;
private ImageView mLoadingView;
private TextView mStateTextView;
private int state = INIT;
private boolean canLoad = true;
private AnimationDrawable mLoadAnim;

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

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

public PullableListView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init(context);
}

private void init(Context context)
{
View view = LayoutInflater.from(context).inflate(R.layout.load_more,
null);
mLoadingView = (ImageView) view.findViewById(R.id.loading_icon);
mLoadingView.setBackgroundResource(R.anim.loading_anim);
mLoadAnim = (AnimationDrawable) mLoadingView.getBackground();
mStateTextView = (TextView) view.findViewById(R.id.loadstate_tv);
addFooterView(view, null, false);
}

@Override
public boolean onTouchEvent(MotionEvent ev)
{
switch (ev.getActionMasked())
{
case MotionEvent.ACTION_DOWN:
// 按下的时候禁止自动加载
canLoad = false;
break;
case MotionEvent.ACTION_UP:
// 松开手判断是否自动加载
canLoad = true;
checkLoad();
break;
}
return super.onTouchEvent(ev);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
super.onScrollChanged(l, t, oldl, oldt);
// 在滚动中判断是否满足自动加载条件
checkLoad();
}

/**
* 判断是否满足自动加载条件
*/
private void checkLoad()
{
if (reachBottom() && mOnLoadListener != null && state != LOADING
&& canLoad)
{
mOnLoadListener.onLoad(this);
changeState(LOADING);
}
}

private void changeState(int state)
{
this.state = state;
switch (state)
{
case INIT:
mLoadAnim.stop();
mLoadingView.setVisibility(View.INVISIBLE);
mStateTextView.setText(R.string.more);
break;

case LOADING:
mLoadingView.setVisibility(View.VISIBLE);
mLoadAnim.start();
mStateTextView.setText(R.string.loading);
break;
}
}

/**
* 完成加载
*/
public void finishLoading()
{
changeState(INIT);
}

@Override
public boolean canPullDown()
{
if (getCount() == 0)
{
// 没有item的时候也可以下拉刷新
return true;
} else if (getFirstVisiblePosition() == 0
&& getChildAt(0).getTop() >= 0)
{
// 滑到ListView的顶部了
return true;
} else
return false;
}

public void setOnLoadListener(OnLoadListener listener)
{
this.mOnLoadListener = listener;
}

/**
* @return footerview可见时返回true,否则返回false
*/
public boolean reachBottom()
{
if (getCount() == 0)
{
// 没有item的时候也可以上拉加载
return true;
} else if (getLastVisiblePosition() == (getCount() - 1))
{
// 滑到底部了
if (getChildAt(getLastVisiblePosition() - getFirstVisiblePosition()) != null
&& getChildAt(
getLastVisiblePosition()
- getFirstVisiblePosition()).getTop() < getMeasuredHeight())
return true;
}
return false;
}

public interface OnLoadListener
{
void onLoad(PullableListView pullableListView);
}
}


Pullable接口是实现下拉刷新的,不用管。代码中判断滑动到底部是根据FooterView的上边缘距离ListView底部的距离。这个功能实现起来没什么难度,其他代码就不贴上来了,下面提供源码下载:

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: