Android ExpandableListView的下拉刷新实现
该控件的修改时根据PullToRefreshList的机制修改
下面是对ExpandableListView的扩展
package com.up91.gwy.view.componet;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.up91.gwy.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ExpandableListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class PullToRefreshExpandableListView
extends ExpandableListView
implements
OnScrollListener {
private static final String TAG = "PullToRefreshExpandableListView";
private static final int TAP_TO_REFRESH = ;
private static final int PULL_TO_REFRESH = ;
private static final int RELEASE_TO_REFRESH = ;
private static final int REFRESHING = ;
private OnRefreshListener mOnRefreshListener;
private OnScrollListener mOnScrollListener;
private LayoutInflater mInflater;
private RelativeLayout mRefreshView;
private TextView mRefreshViewText;
private ImageView mRefreshViewImage;
private ProgressBar mRefreshViewProgress;
private TextView mRefreshViewLastUpdated;
private int mCurrentScrollState;
private int mRefreshState;
private RotateAnimation mFlipAnimation;
private RotateAnimation mReverseFlipAnimation;
private int mRefreshViewHeight;
private int mRefreshOriginalTopPadding;
private int mLastMotionY;
private boolean isInInitState;
public PullToRefreshExpandableListView(Context context) {
super(context);
init(context);
}
public PullToRefreshExpandableListView(Context context, AttributeSet attrs) {
super(context,attrs);
init(context);
}
public PullToRefreshExpandableListView(Context context,AttributeSet attrs, int defStyle) {
super(context,attrs,defStyle);
init(context);
}
private void init(Context context){
mFlipAnimation = new RotateAnimation(,-,
RotateAnimation.RELATIVE_TO_SELF,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
mFlipAnimation.setInterpolator(new LinearInterpolator());
mFlipAnimation.setDuration();
mFlipAnimation.setFillAfter(true);
mReverseFlipAnimation = new RotateAnimation(-,,
RotateAnimation.RELATIVE_TO_SELF,0.5f,
RotateAnimation.RELATIVE_TO_SELF,0.5f);
mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
mReverseFlipAnimation.setDuration();
mReverseFlipAnimation.setFillAfter(true);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRefreshView = (RelativeLayout) mInflater.inflate(R.layout.pull_to_refresh_header, this,false);
mRefreshViewText = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
mRefreshViewImage = (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
mRefreshViewProgress = (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
mRefreshViewLastUpdated = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);
mRefreshViewImage.setMinimumHeight();
mRefreshView.setOnClickListener(new OnClickRefreshListener());
mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();
mRefreshState = TAP_TO_REFRESH;
addHeaderView(mRefreshView);
super.setOnScrollListener(this);
measureView(mRefreshView);
mRefreshViewHeight = mRefreshView.getMeasuredHeight();
}
private void measureView(View child){
ViewGroup.LayoutParams p = child.getLayoutParams();
if(p == null){
p = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(, +, p.width);
int lpHeight = p.height;
int childHeightSpec;
if(lpHeight > ){
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
}else{
childHeightSpec = MeasureSpec.makeMeasureSpec(, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec,childHeightSpec);
}
private class OnClickRefreshListener implements OnClickListener{
@Override
public void onClick(View v) {
if(mRefreshState != REFRESHING){
prepareForRefresh();
onRefresh();
}
}
}
public interface OnRefreshListener{
public void onRefresh();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setSelection();
}
@Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
setSelection();
}
@Override
public void setOnScrollListener(OnScrollListener l) {
mOnScrollListener = l;
}
public void setOnRefreshListener(OnRefreshListener onRefreshListener){
mOnRefreshListener = onRefreshListener;
}
public void setLastUpdated(CharSequence lastUpdated){
if(lastUpdated != null){
mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
mRefreshViewLastUpdated.setText(lastUpdated);
}else{
mRefreshViewLastUpdated.setVisibility(View.GONE);
}
}
public boolean onTouchEvent(MotionEvent event) {
final int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (!isVerticalScrollBarEnabled()) {
setVerticalScrollBarEnabled(true);
}
if (getFirstVisiblePosition() == && mRefreshState != REFRESHING) {
if ((mRefreshView.getBottom() > mRefreshViewHeight
|| mRefreshView.getTop() >= )
&& mRefreshState == RELEASE_TO_REFRESH) {
// Initiate the refresh
mRefreshState = REFRESHING;
prepareForRefresh();
onRefresh();
} else if (mRefreshView.getBottom() < mRefreshViewHeight
|| mRefreshView.getTop() < ) {
// Abort refresh and scroll down below the refresh view
resetHeader();
setSelection();
}
}
break;
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
applyHeaderPadding(event);
break;
}
return super.onTouchEvent(event);
}
private void applyHeaderPadding(MotionEvent ev) {
final int historySize = ev.getHistorySize();
// Workaround for getPointerCount() which is unavailable in 1.5
// (it's always 1 in 1.5)
int pointerCount = ;
try {
Method method = MotionEvent.class.getMethod("getPointerCount");
pointerCount = (Integer)method.invoke(ev);
} catch (NoSuchMethodException e) {
pointerCount = ;
} catch (IllegalArgumentException e) {
throw e;
} catch (IllegalAccessException e) {
System.err.println("unexpected " + e);
} catch (InvocationTargetException e) {
System.err.println("unexpected " + e);
}
for (int h = ; h < historySize; h++) {
for (int p = ; p < pointerCount; p++) {
if (mRefreshState == RELEASE_TO_REFRESH) {
if (isVerticalFadingEdgeEnabled()) {
setVerticalScrollBarEnabled(false);
}
int historicalY = ;
try {
// For Android > 2.0
Method method = MotionEvent.class.getMethod(
"getHistoricalY", Integer.TYPE, Integer.TYPE);
historicalY = ((Float) method.invoke(ev, p, h)).intValue();
} catch (NoSuchMethodException e) {
// For Android < 2.0
historicalY = (int) (ev.getHistoricalY(h));
} catch (IllegalArgumentException e) {
throw e;
} catch (IllegalAccessException e) {
System.err.println("unexpected " + e);
} catch (InvocationTargetException e) {
System.err.println("unexpected " + e);
}
// Calculate the padding to apply, we divide by 1.7 to
// simulate a more resistant effect during pull.
int topPadding = (int) (((historicalY - mLastMotionY)
- mRefreshViewHeight) / 1.7);
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
topPadding,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
}
}
}
private void resetHeaderPadding() {
mRefreshView.setPadding(
mRefreshView.getPaddingLeft(),
mRefreshOriginalTopPadding,
mRefreshView.getPaddingRight(),
mRefreshView.getPaddingBottom());
}
private void resetHeader() {
if (mRefreshState != TAP_TO_REFRESH) {
mRefreshState = TAP_TO_REFRESH;
resetHeaderPadding();
// Set refresh view text to the pull label
mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);
// Replace refresh drawable with arrow drawable
mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);
// Clear the full rotation animation
mRefreshViewImage.clearAnimation();
// Hide progress bar and arrow.
mRefreshViewImage.setVisibility(View.GONE);
mRefreshViewProgress.setVisibility(View.GONE);
}
}
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// When the refresh view is completely visible, change the text to say
// "Release to refresh..." and flip the arrow drawable.
if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL
&& mRefreshState != REFRESHING) {
if (firstVisibleItem == ) {
mRefreshViewImage.setVisibility(View.VISIBLE);
if((mRefreshView.getBottom() > mRefreshViewHeight +
|| mRefreshView.getTop() >= )
&& mRefreshState == PULL_TO_REFRESH){
mRefreshViewText.setText(R.string.pull_to_refresh_release_label);
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mFlipAnimation);
mRefreshState = RELEASE_TO_REFRESH;
}else if(mRefreshState == RELEASE_TO_REFRESH
&&mRefreshView.getBottom() < mRefreshViewHeight + ){
mRefreshViewImage.setVisibility(View.GONE);
resetHeader();
}else if(mRefreshView.getBottom() == mRefreshViewHeight
&& mRefreshState == TAP_TO_REFRESH){
//不作为
mRefreshViewImage.setVisibility(View.GONE);
resetHeader();
} else if(mRefreshView.getBottom() < mRefreshViewHeight +
&& mRefreshState == TAP_TO_REFRESH){
mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);
mRefreshState = PULL_TO_REFRESH;
mRefreshViewImage.clearAnimation();
mRefreshViewImage.startAnimation(mReverseFlipAnimation);
}
} else {
mRefreshViewImage.setVisibility(View.GONE);
resetHeader();
}
} else if (mCurrentScrollState == SCROLL_STATE_FLING
&& firstVisibleItem ==
&& mRefreshState != REFRESHING) {
setSelection();
}
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
public void prepareForRefresh() {
resetHeaderPadding();
mRefreshViewImage.setVisibility(View.GONE);
// We need this hack, otherwise it will keep the previous drawable.
mRefreshViewImage.setImageDrawable(null);
mRefreshViewProgress.setVisibility(View.VISIBLE);
// Set refresh view text to the refreshing label
mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);
mRefreshState = REFRESHING;
}
public void onRefresh() {
if (mOnRefreshListener != null) {
mOnRefreshListener.onRefresh();
resetHeader();
}
}
public void onRefreshComplete(CharSequence lastUpdated) {
setLastUpdated(lastUpdated);
onRefreshComplete();
}
public void onRefreshComplete() {
resetHeader();
// If refresh view is visible when loading completes, scroll down to
// the next item.
if (mRefreshView.getBottom() > ) {
invalidateViews();
setSelection();
}
}
}
使用时:
expLV.setOnRefreshListener(new OnRefreshListener(){
@Override
public void onRefresh() {
//远程取数据机制
});
Android ExpandableListView的下拉刷新实现的更多相关文章
- Android之自定义控件-下拉刷新
实现效果: 图片素材: --> 首先, 写先下拉刷新时的刷新布局 pull_to_refresh.xml: <resources> <string name=& ...
- Android SwipeRefreshLayout 官方下拉刷新控件介绍
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24521483 下面App基本都有下拉刷新的功能,以前基本都使用XListView ...
- android控件 下拉刷新pulltorefresh
外国人写的下拉刷新控件,我把他下载下来放在网盘,有时候訪问不了github 支持各种控件下拉刷新 ListView.ViewPager.WevView.ExpandableListView.GridV ...
- Android内置下拉刷新组件SwipeRefreshLayout
也许下拉刷新之前,你可能会使用一些第三方的开源库,例如PullToRefresh, ActionBar-PullToRefresh等待,但现在有的正式组成部分---SwipeRefreshLayout ...
- 【转载】Android中ListView下拉刷新的实现
在网上看到一个下拉刷新的例子,很的很棒,转载和更多的人分享学习 原文:http://blog.csdn.net/loongggdroid/article/details/9385535 ListVie ...
- Android中ListView下拉刷新的实现
ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考.那我就不解释,直接上代码了. 这里需要自己重写一下ListView,重写代码如下: packa ...
- Android之XListView下拉刷新,更新网络美女图
一.简介: 下拉刷新是一种特定的手动刷新交互,和其他的同类操作不同的地方在于它采用了更加直觉的下拉操作,所以它的交互足够清晰明显. 下拉刷新主要用在类似ListView这样的控件,设计下拉刷新有三 ...
- Android之SwipeRefreshLayout下拉刷新组件
SwipeRefreshLayout概述 SwipeRefrshLayout是Google官方更新的一个Widget,可以实现下拉刷新的效果.该控件集成自ViewGroup在support-v4兼容包 ...
- Android中实现下拉刷新
需求:项目中的消息列表界面要求实现类似sina微博的下拉刷新: 思路:一般的消息列表为ListView类型,将list加载到adapter中,再将adapter加载到 ListView中,从而实现消息 ...
随机推荐
- Foreach 与 Foreach-Object 的区别
下面两个实例可以看出: Get-ADGroupMember -Identity "CN=gAPCHN-HGZ-IE10-Users,OU=Groups,OU=Hangzhou - Chi ...
- 禁用符合一定条件的AD对象 (含Filter参数的写法)
Get-ADComputer -Filter "(sAMAccountType -eq 805306369)" -SearchBase "OU=Computers,OU= ...
- eclipse怎么显示代码行数
熟悉java开发的朋友们肯定有这样的经验,那就是在用eclipse进行java开发的时候,没有显示代码的行数,这并不利于我们进行程序的调试.今天,小编就来教大家eclipse怎么显示代码行数 ...
- 《Java核心技术卷一》笔记 多线程
有时,我们需要在一个程序中同时并行的处理多个任务,如播放器一边要播放音乐同时还要不断更新画面显示,或者是一边执行耗时任务,UI还能一边继续响应各种事件.还有的时候,一个任务需要很长时间才能完成,如果分 ...
- PHP+jQuery 长文章分页类 ( 支持 url / ajax 分页方式 )
/* ******* 环境:Apache2.2.8 ( 2.2.17 ) + PHP5.2.6 ( 5.3.3 ) + MySQL5.0.51b ( 5.5.8 ) + jQuery-1.8 **** ...
- VR制作的规格分析
因为UE4的演示资源更丰富一些,我这边把UE4的有代表性的演示都跑了一遍,同时也通过Rift确认效果,和里面的资源制作方式. 首先,UE4是基于物理渲染的引擎,大部分都是偏向图像真实的.使用的材质 ...
- phpstorm8注册码
phpstorm8注册码 phpstorm 8 注册码 用户名:Learn Programming License key:(包括LICENSE BEGIN和LICENSE END部分) ==== ...
- Bootstrap插件1--tooltip
在引入bootstrap.js之前我们需要引入jquery的js文件 既然是bootstrap的插件,那么自然需要引用bootstrap.js和bootstrap.css这2个核心文件了 这里了主要介 ...
- Nginx模块fastcgi_cache的几个注意点
fastcgi响应http请求的结果中,响应头包括Expires、Cache-Control、Set-Cookie三个,都会可能不被cache. thinkphp3.0禁止session自动启动 co ...
- .Net Install类的Install、Commit等事件触发顺序
.Net Install类的Install.Commit等事件触发顺序 空间 首先是Install其中调用base.Install过程中导致OnBeforeInstallOnAfterInstal ...