自定义listView的上啦加载 带回弹


先看下效果


listview的代码

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.Scroller;
import android.widget.TextView;

public class MyListView extends ListView implements OnScrollListener {

	private boolean isLoadingMore = false;// 是否 滑动到最后一行
	private boolean isLoad = false;// 是否已经是在加载中了

	public static final int state_down_default = 0;// 上啦的 默认状态
	public static final int state_down_loosen = 1;// 上啦的 松开加载
	public static final int state_down_load = 2;// 上啦的 加载中...
	private int loadState = state_down_default;

	private MyListViewListener loadListner;// 上啦加载的监听

	private View footerView;// 加载更多布局
	private TextView fTv;// 显示加载 更多提示
	private int fHeight;// 底部的高度
	private int startY = -1;// 开始的 y坐标
	private Scroller mScroller; // 用来处理回弹的
	private int htTime = 200;// 回弹的总时间 这个决定回弹的速度

	public MyListView(Context context) {
		this(context, null, 0);
	}

	public MyListView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		addLoadXML();
	}

	public void addLoadXML() {
		footerView = View.inflate(getContext(), R.layout.lv_footerview, null);
		this.addFooterView(footerView);
		fTv = (TextView) footerView.findViewById(R.id.tv_lv_footerview);
		fTv.setText("加载更多");
		footerView.measure(0, 0);
		fHeight = footerView.getMeasuredHeight();
		footerView.setPadding(0, -fHeight, 0, 0);// 设置隐藏
		this.setOnScrollListener(this);
		mScroller = new Scroller(getContext(), new DecelerateInterpolator());
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:// 按下
			startY = -1;
			break;
		case MotionEvent.ACTION_MOVE:// 移动
			if (isLoadingMore) {// 只有 滚动到最后一行才会 加载
				if (!isLoad) {// 只有没有加载 才能加载
					if (this.getLastVisiblePosition() == getCount() - 1) {// 并且显示到最后一条
						if (startY == -1) {// 把开始位置放到这里 是因为只有当滑动到最后一行 才开始显示
											// footerView
							startY = (int) ev.getRawY();
						}
						int endY = (int) ev.getRawY();
						int des = Math.abs(endY - startY);
						int padding = des - fHeight;
						footerView.setPadding(0, 0, 0, padding);// 设置显示的高度设置这个就会移动
						if (padding > 40 && loadState == state_down_default) {// 默认状态
																				// 并且大于40
																				// 就设置成松开加载
							loadState = state_down_loosen;
							getRefreshDownstate();
						} else if (padding <= 40
								&& loadState != state_down_default) {// 不是默认状态
																		// 并且滑动的少与40
																		// 就还原成默认的
							loadState = state_down_default;
							getRefreshDownstate();
						}
					}
				}
			}
			break;
		case MotionEvent.ACTION_UP:// 离开
			startY = -1;
			if (isLoadingMore) {
				if (loadState == state_down_loosen) {
					startScroll();// 设置回弹
				} else if (loadState == state_down_default) {// 如果是默认状态
																// 直接隐藏footerView
					footerView.setPadding(0, -fHeight, 0, 0);
				}
			}
			break;
		}
		return super.onTouchEvent(ev);
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {// 这里就是每 小一次回弹 都要取设置 位置
			footerView.setPadding(0, 0, 0, mScroller.getCurrY());
			postInvalidate();// 更新
		}
	}

	/**
	 * 刷新底部
	 */
	private void getRefreshDownstate() {
		switch (loadState) {
		case state_down_default:// 默认状态
			fTv.setText("上啦加载更多");
			isLoad = false;
			break;
		case state_down_loosen:// 松开加载
			fTv.setText("松开加载");
			isLoad = false;
			break;
		case state_down_load:// 加载中
			fTv.setText("加载中...");
			isLoad = true;
			break;
		}
	}

	@Override
	public void onScrollStateChanged(AbsListView arg0, int scrollState) {// 判断是否在滑动
	}

	@Override
	public void onScroll(AbsListView arg0, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {// 判断是 上滑 还是下滑
		// 判断是否滚到最后一行
		if (firstVisibleItem + visibleItemCount == totalItemCount
				&& totalItemCount > 0) {
			isLoadingMore = true;
		} else {
			isLoadingMore = false;
		}
	}

	/**
	 * 回弹的动画
	 */
	public void startScroll() {
		int padding = footerView.getPaddingBottom();
		if (padding > 0) {// 正在加载中 并且回弹
			loadState = state_down_load;
			getRefreshDownstate();
			mScroller.startScroll(0, padding, 0, -padding, htTime);// 这里只要把所有的
																	// padding
																	// 回弹完,就是刚好显示正在加载
			invalidate();
			if (loadListner != null) {
				loadListner.onLoadMore();
			}
		}
	}

	/**
	 * 停止 加载
	 */
	public void stopLoadMore() {
		loadState = state_down_default;
		getRefreshDownstate();
		footerView.setPadding(0, 0, 0, -fHeight);
	}

	/**
	 * 设置 上啦监听
	 */
	public void setLoadListner(MyListViewListener loadListner) {
		this.loadListner = loadListner;
	}

	public interface MyListViewListener {
		public void onLoadMore();
	}

}

里面注释很详细,底部布局可以自己去修改



源码下载




资源下载链接为: https://pan.quark.cn/s/3d8e22c21839 随着 Web UI 框架(如 EasyUI、JqueryUI、Ext、DWZ 等)的不断发展与成熟,系统界面的统一化设计逐渐成为可能,同时代码生成器也能够生成符合统一规范的界面。在这种背景下,“代码生成 + 手工合并”的半智能开发模式正逐渐成为新的开发趋势。通过代码生成器,单表数据模型以及一对多数据模型的增删改查功能可以被直接生成并投入使用,这能够有效节省大约 80% 的开发工作量,从而显著提升开发效率。 JEECG(J2EE Code Generation)是一款基于代码生成器的智能开发平台。它引领了一种全新的开发模式,即从在线编码(Online Coding)到代码生成器生成代码,再到手工合并(Merge)的智能开发流程。该平台能够帮助开发者解决 Java 项目中大约 90% 的重复性工作,让开发者可以将更多的精力集中在业务逻辑的实现上。它不仅能够快速提高开发效率,帮助公司节省大量的人力成本,同时也保持了开发的灵活性。 JEECG 的核心宗旨是:对于简单的功能,可以通过在线编码配置来实现;对于复杂的功能,则利用代码生成器生成代码后,再进行手工合并;对于复杂的流程业务,采用表单自定义的方式进行处理,而业务流程则通过工作流来实现,并且可以扩展出任务接口,供开发者编写具体的业务逻辑。通过这种方式,JEECG 实现了流程任务节点和任务接口的灵活配置,既保证了开发的高效性,又兼顾了项目的灵活性和可扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值