一:实现区别下拉刷新和上拉加载
参考资料:http://blog.csdn.net/losetowin/article/details/18261389
在PullToRefresh的类库的com.handmark.pulltorefresh.library包下,打开PullToRefreshBase.java,在这个类的最后面添加代码。注意,需要重新添加library库。
//根据下拉和上拉显示的布局的可见状态类区分上拉还是下拉,然后执行相应操作 public boolean isHeaderShown() { return getHeaderLayout().isShown(); } public boolean isFooterShown() { return getFooterLayout().isShown(); }
使用方法大概如下:
private boolean isRefreshing = false;//是否正在刷新的标志 private PullToRefreshListView news_list;//列表控件news_list //设置上拉下拉事件 news_list.setOnRefreshListener(new OnRefreshListener<ListView>() { @Override public void onRefresh(PullToRefreshBase<ListView> refreshView) { //在PullToRefresh的类库的com.handmark.pulltorefresh.library包下,打开PullToRefreshBase.java,在这个类的最后面添加代码。注意,需要重新添加library库。 //原理:根据下拉和上拉显示的布局的可见状态类区分上拉还是下拉,然后执行相应操作 if (!isRefreshing) { isRefreshing = true; if(refreshView.isHeaderShown()){ //下拉刷新 业务代码 refreshFirstPage();//刷新第一页数据 }else if(refreshView.isFooterShown()){ //上拉加载 业务代码 loadNextPage();//加载下一页内容 } }else{ //一般来说我们会开另一个线程去获取数据,所以这儿会加上一个判断,如果已经在获取数据了,就onRefreshComplete(),就是将下拉收起;否则就去开新线程取数据,取完记得也要onRefreshComplete()哦 news_list.onRefreshComplete(); isRefreshing = false; } } });
二:实现下拉刷新、下拉加载的图片个性化(图片居中)
参考资料:http://blog.csdn.net/superjunjin/article/details/45022595
定义刷新动画的layout
根据layout中的pull_to_refresh_header_vertical.xml文件修改成如下(图片居中,文字全部设置为gone。不占用空间)
<?xml version="1.0" encoding="utf-8"?> <!-- (1)实现下拉刷新、下拉加载的动画个性化(图片居中) --> <merge xmlns:android="http://schemas.android.com/apk/res/android" > <FrameLayout android:id="@+id/fl_inner" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingBottom="@dimen/header_footer_top_bottom_padding" android:paddingLeft="@dimen/header_footer_left_right_padding" android:paddingRight="@dimen/header_footer_left_right_padding" android:paddingTop="@dimen/header_footer_top_bottom_padding" > <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" > <ImageView android:id="@+id/pull_to_refresh_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> <ProgressBar android:id="@+id/pull_to_refresh_progress" style="?android:attr/progressBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:indeterminate="true" android:visibility="gone" /> </FrameLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:id="@+id/pull_to_refresh_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:textAppearance="?android:attr/textAppearance" android:textStyle="bold" android:visibility="gone" /> <TextView android:id="@+id/pull_to_refresh_sub_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceSmall" android:visibility="gone" /> </LinearLayout> </FrameLayout> </merge>
设置自定义动画效果
设置一个简单的京东小人走的动画效果,在drawable文件夹下新建一个xml
<?xml version="1.0" encoding="utf-8"?> <!-- (2)实现下拉刷新、下拉加载的动画个性化(图片居中) --> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/app_refresh_people_0" android:duration="100"></item> <item android:drawable="@drawable/app_refresh_people_1" android:duration="100"></item> <item android:drawable="@drawable/app_refresh_people_2" android:duration="100"></item> <item android:drawable="@drawable/app_refresh_people_3" android:duration="100"></item> </animation-list>
新建刷新动画的layout,TweenAnimLoadingLayout,类似于之前的源码中的FlipLoadingLayout和RotateLoadingLayout
package com.handmark.pulltorefresh.library.internal; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; import android.util.Log; import android.view.View; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; import com.handmark.pulltorefresh.library.R; /** * (3)实现下拉刷新、下拉加载的动画个性化(图片居中)*/ public class TweenAnimLoadingLayout extends LoadingLayout{ private AnimationDrawable animationDrawable;//创建动画序列对象 public TweenAnimLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) { super(context, mode, scrollDirection, attrs); // TODO Auto-generated constructor stub //初始化 mHeaderImage.setImageResource(R.drawable.jd_refreshlist); animationDrawable = (AnimationDrawable) mHeaderImage.getDrawable(); } // 默认图片 protected int getDefaultDrawableResId() { // TODO Auto-generated method stub return R.drawable.app_refresh_people_0; } @Override protected void onLoadingDrawableSet(Drawable imageDrawable) { } @Override protected void onPullImpl(float scaleOfLayout) { // TODO Auto-generated method stub } // 下拉以刷新 protected void pullToRefreshImpl() { // TODO Auto-generated method stub } // 正在刷新时回调 protected void refreshingImpl() { // 播放帧动画 animationDrawable.start(); } // 释放以刷新 protected void releaseToRefreshImpl() { // TODO Auto-generated method stub } // 重新设置 protected void resetImpl() { mHeaderImage.setVisibility(View.VISIBLE); mHeaderImage.clearAnimation(); } }
替换之前的布局文件,在LoadingLayout类的构造函数中修改引用的布局文件:
public LoadingLayout(Context context, final Mode mode, final Orientation scrollDirection, TypedArray attrs) { super(context); mMode = mode; mScrollDirection = scrollDirection; switch (scrollDirection) { case HORIZONTAL: LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_horizontal, this); break; case VERTICAL: default: //LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_vertical, this); /*(4)实现下拉刷新、下拉加载的动画个性化(图片居中)*/ LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_custom, this); break; }
替换之前的刷新layout为TweenAnimLoadingLayout
找到library项目com.handmark.pulltorefresh.library包下的PullToRefreshListView的createLoadingLayout进入,在createLoadingLayout方法中再进入createLoadingLayout,找到最原始的新建动画layout的地方,把默认的RotateLoadingLayout改成TweenAnimLoadingLayout就行了。在PullToRefreshBase类下:
LoadingLayout createLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) { switch (this) { case ROTATE: default: //return new RotateLoadingLayout(context, mode, scrollDirection, attrs); /*(5)实现下拉刷新、下拉加载的动画个性化(图片居中)*/ return new TweenAnimLoadingLayout(context, mode, scrollDirection, attrs); case FLIP: return new FlipLoadingLayout(context, mode, scrollDirection, attrs); } }
三:实现下拉刷新、下拉加载的动画自定义
1、需要将项目中用到的动画文件和图片资源复制一份到library工程中。
2、主要修改RotateLoadingLayout文件
/******************************************************************************* * Copyright 2011, 2012 Chris Banes. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.handmark.pulltorefresh.library.internal; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Matrix; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; import android.view.View; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.ImageView.ScaleType; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; import com.handmark.pulltorefresh.library.PullToRefreshBase.Orientation; import com.handmark.pulltorefresh.library.R; public class RotateLoadingLayout extends LoadingLayout { static final int ROTATION_ANIMATION_DURATION = 1200; private final Animation mRotateAnimation; private final Matrix mHeaderImageMatrix; private float mRotationPivotX, mRotationPivotY; private final boolean mRotateDrawableWhilePulling; /*(1)实现自定义加载动画*/ private boolean mUseIntrinsicAnimation;//标记传入的drawable是否是AnimationDrawable private AnimationDrawable animationDrawable;//创建动画序列对象 public RotateLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) { super(context, mode, scrollDirection, attrs); mRotateDrawableWhilePulling = attrs.getBoolean(R.styleable.PullToRefresh_ptrRotateDrawableWhilePulling, true); mHeaderImage.setScaleType(ScaleType.MATRIX); mHeaderImageMatrix = new Matrix(); mHeaderImage.setImageMatrix(mHeaderImageMatrix); mRotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR); mRotateAnimation.setDuration(ROTATION_ANIMATION_DURATION); mRotateAnimation.setRepeatCount(Animation.INFINITE); mRotateAnimation.setRepeatMode(Animation.RESTART); } public void onLoadingDrawableSet(Drawable imageDrawable) { /*(2)实现自定义加载动画*/ //如果传进来的是动画,那么 if(imageDrawable instanceof AnimationDrawable){ mUseIntrinsicAnimation = true;//设置标记值为true mHeaderImage.setImageResource(R.drawable.jd_refreshlist);//给图标引用想用的动画(此处需要保证项目中用到的动画文件和图片资源复制一份到library中) animationDrawable = (AnimationDrawable) imageDrawable; } else{ if (null != imageDrawable) { mRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f); mRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f); } } } protected void onPullImpl(float scaleOfLayout) { /*(2)实现自定义加载动画*/ //如果传进来的是动画,那么 if(mUseIntrinsicAnimation){ }else{ float angle; if (mRotateDrawableWhilePulling) { angle = scaleOfLayout * 90f; } else { angle = Math.max(0f, Math.min(180f, scaleOfLayout * 360f - 180f)); } mHeaderImageMatrix.setRotate(angle, mRotationPivotX, mRotationPivotY); mHeaderImage.setImageMatrix(mHeaderImageMatrix); } } // 正在刷新时回调 protected void refreshingImpl() { /*(2)实现自定义加载动画*/ //如果传进来的是动画,那么 if(mUseIntrinsicAnimation){ animationDrawable.start();// 播放帧动画 }else{ mHeaderImage.startAnimation(mRotateAnimation);// 播放帧动画 } } // 重新设置 protected void resetImpl() { /*(2)实现自定义加载动画*/ //如果传进来的是动画,那么 if(mUseIntrinsicAnimation){ mHeaderImage.setVisibility(View.VISIBLE); mHeaderImage.clearAnimation(); }else{ mHeaderImage.clearAnimation(); resetImageRotation(); } } private void resetImageRotation() { /*(2)实现自定义加载动画*/ //如果传进来的是动画,那么 if(mUseIntrinsicAnimation){ }else{ if (null != mHeaderImageMatrix) { mHeaderImageMatrix.reset(); mHeaderImage.setImageMatrix(mHeaderImageMatrix); } } } // 下拉以刷新 protected void pullToRefreshImpl() { // NO-OP } // 释放以刷新 protected void releaseToRefreshImpl() { // NO-OP } // 默认图片 protected int getDefaultDrawableResId() { /*(2)实现自定义加载动画*/ //如果传进来的是动画,那么 if(mUseIntrinsicAnimation){ return R.drawable.app_refresh_people_0; }else{ return R.drawable.default_ptr_rotate; } } }
3、使用方法
//额外的设置:设置下拉刷新和上拉加载的图片和文字,背景颜色等 private void setPullToRefreshAttribute(){ ILoadingLayout startLabels = news_list.getLoadingLayoutProxy(true, false); startLabels.setPullLabel("下拉刷新...");// 刚下拉时,显示的提示 startLabels.setReleaseLabel("松开刷新...");//下来达到一定距离时,显示的提示 startLabels.setRefreshingLabel("正在刷新...");// 刷新时 /*(3)实现自定义加载动画*/ //设置加载动画图标:方式一 AnimationDrawable jdAnimation = (AnimationDrawable) getResources().getDrawable(R.drawable.jd_refreshlist); startLabels.setLoadingDrawable(jdAnimation); ILoadingLayout endLabels = news_list.getLoadingLayoutProxy(false, true); endLabels.setPullLabel("上拉加载...");// 刚下拉时,显示的提示 endLabels.setReleaseLabel("松开加载...");//下来达到一定距离时,显示的提示 endLabels.setRefreshingLabel("正在加载...");// 刷新时 /*(3)实现自定义加载动画*/ //设置加载动画图标:方式二 Drawable drawable2 = (Drawable) getResources().getDrawable(R.drawable.progressbar1); endLabels.setLoadingDrawable(drawable2); }