自个儿写Android的下拉刷新/上拉加载控件

与通常的View配合使用(比如ImageView)

与ListView配合使用

与RecyclerView配合使用

与SrcollView配合使用

局部刷新(但想必这种需要实际应该还是不多的….)

好啦,效果大概就是这样。如果您看后觉得有一点兴趣。那么,以下是相关的信息:

好了,闲话就到这里了。现在正式切入正题,于此逐步简单的记录和总结一下实现这个自定义View的思路以及实现过程。

首先,我们分析一下:假设我们现在的需求是需要让ListView支持下拉刷新和上拉加载,那么其实我们选择去扩展系统自身的ListView是最好的。 但我们这里的初衷是创造一个通用的Pullable的控件,也就是说它可以配合Android中各种View使用。所以,显然我们需要的是一个ViewGroup。 那么,既然有了思路就可以开动了:第一步我们先去创建我们自己的View,并让其继承自ViewGroup。例如就像下面这样:

public class PullableLayout extends ViewGroup{public PullableLayout(Context context) {super(context);}public PullableLayout(Context context, AttributeSet attrs) {super(context, attrs);}}

接下来,我们静静的思考一下所谓的下拉刷新,上拉加载的本质何如。就会发现,其实归根结底原理仍旧是“视图的滚动”而已。 那么,我们来分析下我们为什么会这么说呢?假设现在先在脑海中简单构画一下如下所示的这样一个ViewGroup的结构图:

假设上图中蓝色的部分就是屏幕区域,也就是我们想要呈现内容的区域(比如我们在这里放一个ListView)。而我们的ViewGroup所需要做的工作就是: 为Content部分加上一个Header(头视图)与Footer(尾视图),并且显然Header的位置应该位于Content之上,同理Footer则位于其之下。

那么,在这个基础上,如果我们让整个Viewgroup支持滚动,那么就得以实现一种效果了,即:初始情况下,屏幕上将正常呈现我们的Content视图。 与此同时:当我们上下滑动屏幕,那么当滑动到Content视图的顶部时,就会出现Header视图;当滑动到Content的底部时,则会出现Footer视图。

当然,这种纸上谈兵式的原理性的东西,永远都让人感到无聊。所以,现在我们实际的来“兑换”一下我们目前为止谈到的这种效果。看以下布局文件:

左边的布局非常简单和熟悉,就是显示一个宽高填满父窗口的ImageView。而在右边我们则是把父布局替换成了我们自定义的PullableLayout。

好的,现在我们就一起来看看,我们应该怎么样逐步完善PullableLayout让它实现我们说到的效果。 首先,既然我们说到需要一个Header与Footer。那么,我们就先来定义好这两个东东的布局。比如说,我们定义一个如下的Header布局:

这个布局还是非常简单明了的。同样的,Footer布局的定义其实与Header是非常类似的,所以就不再贴一次代码了。 准备好Header与Footer布局后,我们应该考虑的工作,就是怎么把它们按照我们的需要给“放进”我们自己的PullableLayout当中了,其实这并不难。

private View mHeader,mFooter;public PullableLayout(Context context, AttributeSet attrs) {super(context, attrs);mHeader = LayoutInflater.from(context).inflate(R.layout.header_pullable_layout,null);mFooter = LayoutInflater.from(context).inflate(R.layout.footer_pullable_layout,null);}@Overrideprotected void onFinishInflate() {super.onFinishInflate();// 看这里哦,亲RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT);mHeader.setLayoutParams(params);mFooter.setLayoutParams(params);addView(mHeader);addView(mFooter);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 测量for (int i = 0; i < getChildCount(); i++){View child = getChildAt(i);measureChild(child,widthMeasureSpec,heightMeasureSpec);}}private int mLayoutContentHeight;@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {mLayoutContentHeight = 0;// 置位for (int i = 0; i < getChildCount(); i++){View child = getChildAt(i);if (child == mHeader) { // 头视图隐藏在顶端child.layout(0, 0 – child.getMeasuredHeight(), child.getMeasuredWidth(), 0);} else if (child == mFooter) { // 尾视图隐藏在layout所有内容视图之后child.layout(0, mLayoutContentHeight, child.getMeasuredWidth(), mLayoutContentHeight + child.getMeasuredHeight());} else { // 内容视图根据定义(插入)顺序,按由上到下的顺序在垂直方向进行排列child.layout(0, mLayoutContentHeight, child.getMeasuredWidth(), mLayoutContentHeight + child.getMeasuredHeight());mLayoutContentHeight += child.getMeasuredHeight();}}}

以上的代码也并不复杂,核心的工作就是填充Header与Footer视图,并且按需要进行测量和置位的工作。如果作为新手来说,值得注意的可能就是:

不敢接受失败的人,往往是那些追求完美的人,

自个儿写Android的下拉刷新/上拉加载控件

相关文章:

你感兴趣的文章:

标签云: