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中,从而实现消息 ...
随机推荐
- Nodejs - windows的系统变量(环境变量)
我的电脑-属性-高级-环境变量-系统变量(s)-Path 将Node.exe所在的路径插入Path的变量值(V)中 如 ;E:\nodejs\ 最终效果 C:\Windows\system32;C:\ ...
- C# - Lee 公共类库
我的公共类库 using System; using System.IO; using System.Net; using System.Security.Cryptography; using Sy ...
- io资料
jitsi red5 apache meeting2 openmeeting2 openfire http://www.onlycoder.net/ 在视频会议领域,有许多可以值得参考的开源项目,这些 ...
- Sql Server 常用方法、存储过程备用
常用方法 --字符串转换成数字 --CAST("1" AS int) --CONVERT(int,"1") --截取字符串 SUBSTRING(OccurreA ...
- Javascript 笔记与总结(2-10)删除节点,创建节点
[删除节点] 步骤: ① 找到对象 ② 找到他的父对象 parentObj ③ parentObj.removeChild(子对象); [例] <!DOCTYPE html> <ht ...
- selenium 使用笔记
下面一段代码是使用selenium访问网页一个小实例 #!/usr/bin/python# -*- coding: utf-8 -*- '''Created on Dec 6, 2013 @autho ...
- System.Data.OracleClient.OracleConnection已过时
解决办法如下: 1.把原来的using System.Data.OracleClient;去掉 2.在oracle安装目录下找到Oracle.DataAccess.dll 添加引用:using Ora ...
- Bootstrap页面布局12 - BS表单元素的排版
首先看看这行代码: <label for='account'>帐 号</label> <input id='account' name='account' type='t ...
- Python操作MySQL以及中文乱码的问题
Python操作MySQL需要安装Python-MySQL可以从网上搜索一下,和一般的Python包一样安装 安装好之后,模块名字叫做MySQLdb ,在Window和Linux环境下都可以使用,试验 ...
- 【php学习】mysql数据库操作
//建立数据库连接,数据库地址127.0.0,用户名root,密码root $dbConn = mysql_connect('127.0.0.1', 'root', 'root'); mysql_qu ...