版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sumsear/article/details/53674063
Android 的SwipeRefreshLayout是一个比较好的下拉刷新控件,现在已经有越来越多的企业开始使用这个控件了。但是遗憾的是这个控件并没有上拉加载更多的功能,所以自己抽空,根据网上已有的例子,自己写了一个。
首先必须要做的是创建一个类继承SwipeRefreshLayout,这里我把它命名为:XZHRefreshLayout
/**
* TODO:Created by XuZhenhao on 2016/12/6.
*/
public class XZHRefreshLayout extends SwipeRefreshLayout {
private boolean isLoading = false;
private ListView mListView;
private View mListFooter;
private OnLoadListener mLoadListener;
public XZHRefreshLayout(Context context) {
this(context, null);
}
public XZHRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
//这里初始化FooterView,并给里面的一个菊花图片添加一个动画
mListFooter = LayoutInflater.from(context).inflate(R.layout.list_footer, null, false);
Animation anim = AnimationUtils.loadAnimation(context, R.anim.img_animation);
LinearInterpolator lin = new LinearInterpolator();
anim.setInterpolator(lin);
mListFooter.findViewById(R.id.progress_iv).startAnimation(anim);
}
//这里set回调函数
public void setOnLoadListener(OnLoadListener loadListener) {
this.mLoadListener = loadListener;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//这里判断ViewGroup里面是不是有个子View,并且第一个是不是ListView
int childCount = getChildCount();
if (childCount > 0) {
View child = getChildAt(0);
if (child instanceof ListView) {
mListView = (ListView) child;
}
}
}
//用于添加和移除FooterView
public void setLoad(boolean isLoad) {
isLoading = isLoad;
if (isLoad) {
mListView.addFooterView(mListFooter);
} else {
mListView.removeFooterView(mListFooter);
}
}
//记录手指触摸屏幕的上一个Y坐标值
private float lastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
float currentY = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
//如果当前的Y坐标小于上一个Y坐标的值说明是向上滑动,,并且子ListView不为null,并且没有FooterView
if (currentY < lastY && mListView != null && mListView.getFooterViewsCount() == 0) {
//如果当前listView的最后一个item的position等于可见范围内最后一个item的position,
//并且屏幕中的item总数小于11,当前没有加载FooterView
if (mListView.getAdapter().getCount() - 1 == mListView.getLastVisiblePosition()
&& mListView.getChildCount() >= 11 && !isLoading) {
setLoad(true);//添加FooterView
mLoadListener.onLoad();//执行回调函数
}
}
break;
}
lastY = currentY;
return super.onInterceptTouchEvent(ev);
}
//回调
public interface OnLoadListener {
void onLoad();
}
}
最核心的代码已经实现了,网上有很多Demo是在onScroll方法中实现的,但是我发现在滑动到底部时,onScroll方法一直在执行,那么这样的话会导致我们一直的执行回调函数,因为这里的回调函数是用来加载数据的,从而会导致不停地获取数据,不停的添加和移除FooterView,并且导致ListView的点击事件失效,所以我将其移到了onInterceptTouchEvent(MotionEvent ev)里面去执行。
下面上Activity的代码:
public class MessageListActivity extends AppCompatActivity {
private Toolbar SMSToolbar;
private XZHRefreshLayout refreshLayout;
private ListView lvSMSList;
private MessageListAdapter adapter;
private List smsList;
private MRLTDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_list);
initData();
initView();
}
/**
* TODO: 初始化控件
*/
private void initView() {
SMSToolbar = (Toolbar) findViewById(R.id.sms_list_toolbar);
SMSToolbar.setTitle("短信列表");
SMSToolbar.setNavigationIcon(ContextCompat.getDrawable(this, R.mipmap.btn_back));
SMSToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
//实现我们自定义的下拉刷新控件
refreshLayout = (XZHRefreshLayout) findViewById(R.id.refresh_sms_ly);
refreshLayout.setColorSchemeColors(ContextCompat.getColor(this, android.R.color.holo_blue_bright),
ContextCompat.getColor(this, android.R.color.holo_green_light),
ContextCompat.getColor(this, android.R.color.holo_orange_light),
ContextCompat.getColor(this, android.R.color.holo_red_light));
//监听下拉刷新事件
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
smsList.clear();
smsList.addAll(dao.querySMSALL(0));
adapter.notifyDataSetChanged();
refreshLayout.setRefreshing(false);
}
}, 1500);
}
});
//我们写的回调函数,在里面做查找数据的方法
refreshLayout.setOnLoadListener(new XZHRefreshLayout.OnLoadListener() {
@Override
public void onLoad() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//我这里是用了一个Sqlite,大家可以根据自己的实际应用在这里做数据的查询,相信大家一般都不可能会有问题。
if (dao != null && smsList != null) {
List<SmsEntity> datas = dao.querySMSALL(smsList.size());
if (datas.size() > 0) {//如果查询到有数据,就添加到数据源里面去。
smsList.addAll(datas);
adapter.notifyDataSetChanged();
}else{//如果没有数据,就弹一个吐司
MyToast.show(MessageListActivity.this,"没有更多数据!");
}
}
refreshLayout.setLoad(false);
}
}, 1000);
}
});
lvSMSList = (ListView) findViewById(R.id.sms_list_lv);
adapter = new MessageListAdapter(this, smsList);
lvSMSList.setAdapter(adapter);
lvSMSList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SmsEntity entity = (SmsEntity) adapter.getItem(position);
showSMSDialog(entity);
}
});
}
/**
* TODO: 初始化数据
*/
private void initData() {
if (smsList == null)
smsList = new ArrayList<>();
if (dao == null)
dao = new MRLTDao(getApplicationContext());
smsList = dao.querySMSALL(0);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
//点击item弹一个Dialog,显示当前Item的内容
private void showSMSDialog(SmsEntity entity) {
if (entity == null) {
return;
}
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(entity.getSendcode());
builder.setMessage("接收时间:"+entity.getCreate_time()+"\n"+entity.getContent());
builder.setPositiveButton("知道了", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.create().show();
}
}
总的来说Activity里面完全没有啥技术含量,只是有可能代码写的其丑无比。
下面上XML:
1.Activity的XML文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_message_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.yihuacomputer.sdmrlt.ui.MessageListActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/sms_list_toolbar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/cpb_blue"
app:titleTextColor="@color/cpb_white" />
<com.yihuacomputer.sdmrlt.ui.view.XZHRefreshLayout
android:id="@+id/refresh_sms_ly"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/sms_list_toolbar">
<ListView
android:id="@+id/sms_list_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:scrollbars="none">
</ListView>
</com.yihuacomputer.sdmrlt.ui.view.XZHRefreshLayout>
</RelativeLayout>
2.ListView的Item的XML
<?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:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:weightSum="10">
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@mipmap/will" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="9"
android:layout_marginLeft="4dp">
<TextView
android:id="@+id/item_sms_rvd_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimaryDark"
android:maxLength="15"
android:textSize="16sp" />
<TextView
android:id="@+id/item_sms_time_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimaryDark"
android:textSize="16sp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" />
<TextView
android:id="@+id/item_sms_content_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/item_sms_rvd_tv"
android:maxLines="1"
android:textColor="@color/menu_fragment_background"
android:textSize="14sp" />
</RelativeLayout>
</LinearLayout>
3.FooterView的XML文件
<?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="45dp"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/progress_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/gpu" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载..."/>
</LinearLayout>
所有的XML文件里面就用到了两个Image,大家随便去找两个就可以了,我是解压了手机QQ的App后这里面找的。
好了所有的东西基本已经实现,大家还可以在这个基础上扩展一下,比如加一个动画,让FooterView被移除的时候好看一点,不要那么突兀的就消失了,如果大家实现了,希望能留个言让我学习学习!!!公司没有录屏工具,我就不上图了。