Android 仿硅谷新闻下拉刷新/上拉加载更多
作者:ganchuanpu 发布时间:2023-03-25 14:19:11
标签:android,下拉刷新,上拉加载
1.添加加载更多布局
1_初始化和隐藏代码
在RefreshListView构造方法中调用
private void initFooterView(Context context) {
View footerView = View.inflate(context, R.layout.refresh_listview_footer, null);
//隐藏代码
footerView.measure(0, 0);
int footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -footerViewHeight, 0, 0);
this.addFooterView(footerView);
}
2_布局文件refresh_listview_footer.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="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ProgressBar
android:layout_margin="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/custom_progressbar" />
<TextView
android:layout_marginLeft="10dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加载更多中..."
android:textColor="#ff0000"
android:textSize="25sp" />
</LinearLayout>
2.拖动到底部的时候
/**
* 菜单页面对应的新闻页签页面
* 总共有12个
* @author Administrator
*
*/
public class TabMenuDetailPager extends MenuDetailBasePagerimplements OnPageChangeListener {
/**
* 新闻中心-新闻菜单对应的标签对应的数据
*/
private NewCenterTag newCenterTag;
.......................
/**
* 加载更多数据的URL
*/
private String moreUrl;
/**
* 是否加载更多数据中
*/
protected boolean isLoadingMore = false;
...................
@Override
public View initView() {
View view = View.inflate(mActivity, R.layout.tab_detail, null);
//把View注入到XUtils框架中
ViewUtils.inject(this, view);
..........................
//设置监听下拉刷新
mListView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onPullDownRefresh() {
isPullDownRefreshing = true;
getDataFromNet();
}
@Override
public void onLoadingMore() {
if(TextUtils.isEmpty(moreUrl)){
Toast.makeText(mActivity, "没有更多数据了", 1).show();
mListView.onRefreshFinish(false);
}else{
//有更多数据,要加载更多数据了
getMoreDataFromNet();
}
}
});
return view;
}
/**
* 加载更多数据
*/
protected void getMoreDataFromNet() {
HttpUtils httpUtils = new HttpUtils();
httpUtils.send(HttpMethod.GET, moreUrl, new RequestCallBack<String>() {
@Override
public void onSuccess(ResponseInfo<String> responseInfo) {
System.out.println("加载更多数据成功:"+responseInfo.result);
mListView.onRefreshFinish(false);
isLoadingMore = true;
processData(responseInfo.result);
}
@Override
public void onFailure(HttpException error, String msg) {
mListView.onRefreshFinish(false);
System.out.println("加载更多数据失败:"+ msg);
}
});
}
/**
* 处理和解析json数据
* @param json
*/
protected void processData(String json) {
TabDetailBean bean = parserJson(json);
if(!isLoadingMore){
System.out.println(bean.data.news.get(0).title);
topnews = bean.data.topnews;
//给ViewPager设置适配器
TabDetailAdapter adapter = new TabDetailAdapter();
mViewPager.setAdapter(adapter);
// 把所有的View清除
ll_point_group.removeAllViews();
for(int i=0;i<topnews.size();i++){
View point = new View(mActivity);
LayoutParams params = new LayoutParams(5, 5) ;
point.setBackgroundResource(R.drawable.tab_detail_point_bg);
if(i!=0){
params.leftMargin = 10;
}
point.setEnabled(false);
point.setLayoutParams(params);
ll_point_group.addView(point);
}
previousPointPosition = 0;
//设置默认的图片描述和指示点
mtv_title_description.setText(topnews.get(previousPointPosition).title);
ll_point_group.getChildAt(previousPointPosition).setEnabled(true);
//设置页面改变的监听
mViewPager.setOnPageChangeListener(this);
//设置适配器和对应的数据
newsLists = bean.data.news;
listViewAdapter = new ListViewAdapter();
mListView.setAdapter(listViewAdapter);
// mListView.addHeaderView(v) ;//把一个视图一头的方式添加到ListView中
}else{
//把列表新闻取出来,在加载到以前的集合中,在刷新数据
isLoadingMore = false;
List<News>moreDataNews = bean.data.news;
newsLists.addAll(moreDataNews);
listViewAdapter.notifyDataSetChanged();//刷新数据
}
}
................
/**
* 用Gson开源项目解析json
* @param json
*/
private TabDetailBean parserJson(String json) {
Gson gson = new Gson();
TabDetailBean bean = gson.fromJson(json, TabDetailBean.class);
moreUrl = bean.data.more;
if(TextUtils.isEmpty(moreUrl)){
moreUrl = null;
}else{
moreUrl = ConstantUtils.server_url+moreUrl;
}
return bean;
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
...............
}
3.完整代码
package com.atguigu.refreshlistview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 作用:自定义下拉刷新的ListView
*/
public class RefreshListview extends ListView {
/**
* 下拉刷新和顶部轮播图
*/
private LinearLayout headerView;
/**
* 下拉刷新控件
*/
private View ll_pull_down_refresh;
private ImageView iv_arrow;
private ProgressBar pb_status;
private TextView tv_status;
private TextView tv_time;
/**
* 下拉刷新控件的高
*/
private int pullDownRefreshHeight;
/**
* 下拉刷新
*/
public static final int PULL_DOWN_REFRESH = 0;
/**
* 手松刷新
*/
public static final int RELEASE_REFRESH = 1;
/**
* 正在刷新
*/
public static final int REFRESHING = 2;
/**
* 当前状态
*/
private int currentStatus = PULL_DOWN_REFRESH;
private Animation upAnimation;
private Animation downAnimation;
/**
* 加载更多的控件
*/
private View footerView;
/**
* 加载更多控件高
*/
private int footerViewHeight;
/**
* 是否已经加载更多
*/
private boolean isLoadMore = false;
/**
* 顶部轮播图部分
*/
private View topNewsView;
/**
* ListView在Y轴上的坐标
*/
private int listViewOnScreenY = -1;
public RefreshListview(Context context) {
this(context, null);
}
public RefreshListview(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RefreshListview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initHeaderView(context);
initAnimation();
initFooterView(context);
}
private void initFooterView(Context context) {
footerView = View.inflate(context, R.layout.refresh_footer, null);
footerView.measure(0, 0);
footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -footerViewHeight, 0, 0);
//ListView添加footer
addFooterView(footerView);
//监听ListView的滚动
setOnScrollListener(new MyOnScrollListener());
}
/**
* 添加顶部轮播图
* @param topNewsView
*/
public void addTopNewsView(View topNewsView) {
if(topNewsView != null){
this.topNewsView =topNewsView;
headerView.addView(topNewsView);
}
}
class MyOnScrollListener implements OnScrollListener{
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//当静止或者惯性滚动的时候
if(scrollState ==OnScrollListener.SCROLL_STATE_IDLE||scrollState ==OnScrollListener.SCROLL_STATE_FLING){
//并且是最后一条可见
if(getLastVisiblePosition()>=getCount()-1){
//1.显示加载更多布局
footerView.setPadding(8,8,8,8);
//2.状态改变
isLoadMore = true;
//3.回调接口
if(mOnRefreshListener != null){
mOnRefreshListener.onLoadMore();
}
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
}
private void initAnimation() {
upAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(500);
upAnimation.setFillAfter(true);
downAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(500);
downAnimation.setFillAfter(true);
}
private void initHeaderView(Context context) {
headerView = (LinearLayout) View.inflate(context, R.layout.refresh_header, null);
//下拉刷新控件
ll_pull_down_refresh = headerView.findViewById(R.id.ll_pull_down_refresh);
iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
pb_status = (ProgressBar) headerView.findViewById(R.id.pb_status);
tv_status = (TextView) headerView.findViewById(R.id.tv_status);
tv_time = (TextView) headerView.findViewById(R.id.tv_time);
//测量
ll_pull_down_refresh.measure(0, 0);
pullDownRefreshHeight = ll_pull_down_refresh.getMeasuredHeight();
//默认隐藏下拉刷新控件
// View.setPadding(0,-控件高,0,0);//完全隐藏
//View.setPadding(0, 0,0,0);//完全显示
ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0);
//添加ListView的头
addHeaderView(headerView);
}
private float startY = -1;
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//1.记录起始坐标
startY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (startY == -1) {
startY = ev.getY();
}
//判断顶部轮播图是否完全显示,只有完全显示才会有下拉刷新
boolean isDisplayTopNews = isDisplayTopNews();
if(!isDisplayTopNews){
//加载更多
break;
}
//如果是正在刷新,就不让再刷新了
if (currentStatus == REFRESHING) {
break;
}
//2.来到新的坐标
float endY = ev.getY();
//3.记录滑动的距离
float distanceY = endY - startY;
if (distanceY > 0) {//下拉
//int paddingTop = -控件高 + distanceY;
int paddingTop = (int) (-pullDownRefreshHeight + distanceY);
if (paddingTop < 0 && currentStatus != PULL_DOWN_REFRESH) {
//下拉刷新状态
currentStatus = PULL_DOWN_REFRESH;
//更新状态
refreshViewState();
} else if (paddingTop > 0 && currentStatus != RELEASE_REFRESH) {
//手松刷新状态
currentStatus = RELEASE_REFRESH;
//更新状态
refreshViewState();
}
ll_pull_down_refresh.setPadding(0, paddingTop, 0, 0);
//View.setPadding(0,paddingTop,0,0);//动态的显示下拉刷新控件
}
break;
case MotionEvent.ACTION_UP:
startY = -1;
if (currentStatus == PULL_DOWN_REFRESH) {
// View.setPadding(0,-控件高,0,0);//完全隐藏
ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0);
} else if (currentStatus == RELEASE_REFRESH) {
//设置状态为正在刷新
currentStatus = REFRESHING;
refreshViewState();
// View.setPadding(0,0,0,0);//完全显示
ll_pull_down_refresh.setPadding(0, 0, 0, 0);
//回调接口
if (mOnRefreshListener != null) {
mOnRefreshListener.onPullDownRefresh();
}
}
break;
}
return super.onTouchEvent(ev);
}
/**
* 判断是否完全显示顶部轮播图
* 当ListView在屏幕上的Y轴坐标小于或者等于顶部轮播图在Y轴的坐标的时候,顶部轮播图完全显示
* @return
*/
private boolean isDisplayTopNews() {
if(topNewsView != null){
//1.得到ListView在屏幕上的坐标
int[] location = new int[2];
if(listViewOnScreenY == -1){
getLocationOnScreen(location);
listViewOnScreenY = location[1];
}
//2.得到顶部轮播图在屏幕上的坐标
topNewsView.getLocationOnScreen(location);
int topNewsViewOnScreenY = location[1];
// if(listViewOnScreenY <= topNewsViewOnScreenY){
// return true;
// }else{
// return false;
// }
return listViewOnScreenY <= topNewsViewOnScreenY;
}else{
return true;
}
}
private void refreshViewState() {
switch (currentStatus) {
case PULL_DOWN_REFRESH://下拉刷新状态
iv_arrow.startAnimation(downAnimation);
tv_status.setText("下拉刷新...");
break;
case RELEASE_REFRESH://手松刷新状态
iv_arrow.startAnimation(upAnimation);
tv_status.setText("手松刷新...");
break;
case REFRESHING://正在刷新状态
tv_status.setText("正在刷新...");
pb_status.setVisibility(VISIBLE);
iv_arrow.clearAnimation();
iv_arrow.setVisibility(GONE);
break;
}
}
/**
* 当联网成功和失败的时候回调该方法
* 用户刷新状态的还原
*
* @param sucess
*/
public void onRefreshFinish(boolean sucess) {
if(isLoadMore){
//加载更多
isLoadMore = false;
//隐藏加载更多布局
footerView.setPadding(0,-footerViewHeight,0,0);
}else{
//下拉刷新
tv_status.setText("下拉刷新...");
currentStatus = PULL_DOWN_REFRESH;
iv_arrow.clearAnimation();
pb_status.setVisibility(GONE);
iv_arrow.setVisibility(VISIBLE);
//隐藏下拉刷新控件
ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0);
if (sucess) {
//设置最新更新时间
tv_time.setText("上次更新时间:" + getSystemTime());
}
}
}
/**
* 得到当前Android系统的时间
*
* @return
*/
private String getSystemTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(new Date());
}
/**
* 监听控件的刷新
*/
public interface OnRefreshListener {
/**
* 当下拉刷新的时候回调这个方法
*/
public void onPullDownRefresh();
/**
当加载更多的时候回调这个方法
*/
public void onLoadMore();
}
private OnRefreshListener mOnRefreshListener;
/**
* 设置监听刷新,由外界设置
*/
public void setOnRefreshListener(OnRefreshListener l) {
this.mOnRefreshListener = l;
}
}
以上所述是小编给大家介绍的Android 仿硅谷新闻下拉刷新/上拉加载更多网站的支持!
来源:http://www.cnblogs.com/ganchuanpu/archive/2016/10/27/6006180.html
0
投稿
猜你喜欢
- file.mkdir()创建单级文件夹,file.mkdirs()创建多级文件夹,file.createNewFile()创建的是一个文件。
- 在Java 字符终端上获取输入有三种方式:1、java.lang.System.in (目前JDK版本均支持)2、java.util.Sca
- 一、前言canal:阿里巴巴 MySQL binlog 增量订阅&消费组件https://github.com/alibaba/ca
- 在C# winform应用程序中,用以下代码可以进行一些内存使用的优化using System;using System.Diagnosti
- Java的super关键字当子类重写父类的方法后,子类对象将无法直接访问父类被重写的方法。为了解决这个问题,在Java中专门提供了一个sup
- 本文实例讲述了Android编程简单实现ImageView点击时背景图修改的方法。分享给大家供大家参考,具体如下:在使用ImageView时
- 本文实例为大家分享了Unity使用摄像机实现望远镜效果的具体代码,供大家参考,具体内容如下听起来挺酷炫,其实超简单,就是控制摄像机的fiel
- JVM内存模型/内存空间Java虚拟机JVM运行起来,就会给内存划分空间,这块空间成为运行时数据区。运行时数据区主要划分为以下 6
- 第一步:引入jar包 <dependency> <gro
- 一、安装及配置Genymotion(1)由于Eclipse中自带的SDK模拟器,启动之慢,不说了 现在给大家介绍一种比较快的模拟器Genym
- 前言此前部门内的一个线上系统上线后内存一路飙高、一段时间后直接占满。协助开发人员去分析定位,发现内存中某个Object的量远远超出了预期的范
- 前言在前面的文章中其实大家也已经看到我使用过collect(Collectors.toList()) 将数据最后汇总成一个 List 集合。
- 本文实例讲述了Java Swing实现让窗体居中显示的方法。分享给大家供大家参考,具体如下:Swing组件是AWT组建的增强组件,是功能强大
- Android listview的滑动冲突解决方法在Android开发的过程中,有时候会遇到子控件和父控件都要滑动的情况,尤其是当子控件为l
- FROM子句一、简单FROM子句获取数据源:var queryAllCustomers = &nb
- 十进制整数与其他进制的字符串之间的转换。c#中十六进制用前缀0x表示。int c = 0x1000;一、利用Convert.ToString
- XSS ,全名:cross-site scripting(跨站点脚本),是当前 web 应用中最危险和最普遍的漏洞之一。攻击者尝试注入恶意脚
- 下面就列出配置eclipse联想功能(代码的提示功能)的步骤:1. 打开Eclipse,然后“window”→“Preferences”2.
- 在开发中经常使用到Set集合去重,那么去重的原理是怎样实现的呢?在此文章记录一下去重原理!!!下面是set集合类图下面我们来跟踪一下执行过程
- RestTemplate未设置超时时间,导致RabbitMQ队列大量堆积,消费者假死,不进行消费,类似线程堵塞。排查:从日志排查问题,在从进