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中,从而实现消息 ...
随机推荐
- 大数据技术hadoop入门理论系列之二—HDFS架构简介
HDFS简单介绍 HDFS全称是Hadoop Distribute File System,是一个能运行在普通商用硬件上的分布式文件系统. 与其他分布式文件系统显著不同的特点是: HDFS是一个高容错 ...
- [百科]sys/types.h
sys/types.h中文名称为基本系统数据类型.在应用程序源文件中包含 <sys/types.h> 以访问 _LP64 和 _ILP32 的定义.此头文件还包含适当时应使用的多个基本派生 ...
- cmd命令行查看windows版本
1.ver命令不显示sp几 C:\>ver Microsoft Windows XP [Version 5.1.2600] C:\> 08: C:\Users\Administrator& ...
- [转]WinForm和WebForm下读取app.config web.config 中邮件配置的方法
本文转自:http://blog.csdn.net/jinbinhan/article/details/1598386 1. 在WinForm下读取 App.config中的邮件配置语句如下: Con ...
- 【液晶模块系列基础视频】1.2.iM_RGB模块介绍
[液晶模块系列基础视频]1.2.iM_RGB模块介绍(上) [液晶模块系列基础视频]1.2.iM_RGB模块介绍(下) ============================== 技术论坛:http ...
- 彻底搞清楚字符编码: ASCII, ISO_8859, GB2312,UCS, Unicode, Utf-8
彻底搞清楚字符编码: ASCII, ISO_8859, GB2312,UCS, Unicode, U 1.ASCII: 0-127(128-255未使用),美国标准 2.IS0-8859-1(lati ...
- P4factory <Towards a better behavioral model: bmv2>
尝试使用bmv2行为模型来跑p4实例. 原文说明: We have released a new version of the behavioral model, written in C++. So ...
- 查找文件是否安装以及安装路径(Ubuntu 下 )
参考:<linux下如何查看某个软件 是否安装??? 安装路径在哪???> 原文: 如果你使用rpm -ivh matlab装的, 用rpm -qa | grep matlab肯定是能够找 ...
- 放到u-boot/arch/arm/inlcude下面解压A20固件库制作笔记
运行 build_dragonboard.sh,完成一次编译,首次编译需要消耗 20 分钟以上的时间.这里包括编译bootloader.kernel.rootfs. 修改 Linux 内核配置$ cd ...
- 嵌入式Linux的FTP服务端软件(stupid-ftpd)
我自己试没成功 http://blog.csdn.net/gzshun/article/details/7358651