网上的下拉刷新功能很多,不过基本上都是隐藏header的,而项目里面需要只隐藏部分的header,类似QQ好友动态的效果,修改了一些现有的,最后有很多问题,所以就自己自定义了一个,逻辑也很简单,首先就是重写ListView,然后覆写onTouchEvent,然后根据手的触摸位置计算差值,然后移动header.下面是效果图:

主要的部分就是下拉刷新组件,代码如下,里面我都要注释:

package com.jwzhangjie.mypullrefresh;

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.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView; public class PullReFreshLibrary extends ListView{
//下拉的父布局
private LinearLayout conterViewLayout;
//实现下拉的头部
private RelativeLayout headerView;
//提示下拉状态
private TextView pullTextView;
private LayoutInflater mInflater;
//下拉框的高度
private int headviewHeight;
//下拉框距离顶部的初始高度
private int initHeight;
//手按下去的y轴坐标
private int initPosition = 0;
//最新的手的y轴坐标
private int lastPositon =0;
//下拉移动的最小距离
private int minMarge = 5;
//当前下拉head的距离顶部的高度
private int currentHeight = -100;
//下拉head的各种状态
private static enum State{
PULL_TO_REFRESH,
RELEASE_TO_REFRESH,
REFRESHING,
REFRESHCOMPLETE,
}
private State state = State.PULL_TO_REFRESH; public PullReFreshLibrary(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
conterViewLayout = (LinearLayout) mInflater.inflate(R.layout.headview, null);
headerView = (RelativeLayout)conterViewLayout.findViewById(R.id.testHeader);
pullTextView = (TextView)headerView.findViewById(R.id.pullTextView);
headviewHeight = (int)context.getResources().getDimensionPixelSize(R.dimen.header_view_height);
initHeight = (int)context.getResources().getDimensionPixelSize(R.dimen.init_height);
addHeaderView(conterViewLayout);
} @Override
public boolean onTouchEvent(MotionEvent ev) {
if (state == State.REFRESHING) {
return true;
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
initPosition = (int)ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (getFirstVisiblePosition() == 0) {
lastPositon = (int)ev.getY();
int diff = lastPositon - initPosition;
if (Math.abs(diff) > minMarge) {
diff = (int)(diff / 2.7);
}
initPosition = lastPositon;
int newHeaderPadding = Math.max(Math.round(currentHeight + diff), -headviewHeight);
if (state != State.REFRESHING && newHeaderPadding != currentHeight) {
if (newHeaderPadding > 0) {
currentHeight = 0;
}else {
currentHeight = newHeaderPadding;
}
margeTop();
}
}
break;
case MotionEvent.ACTION_UP:
if (state == State.RELEASE_TO_REFRESH) {
setState(State.RELEASE_TO_REFRESH);
}else if (getFirstVisiblePosition() == 0 && currentHeight > -initHeight) {
resetHeader();
}
break;
}
return super.onTouchEvent(ev);
} /**
* 设置下拉head的状态以及处理功能
* @param state
*/
private void setState(State state){
this.state = state;
switch (state) {
case PULL_TO_REFRESH:
pullTextView.setVisibility(View.VISIBLE);
pullTextView.setText("下拉刷新");
break;
case RELEASE_TO_REFRESH:
if (onRefreshListener == null) {
state = State.PULL_TO_REFRESH;
resetHeader();
}else {
state = State.REFRESHING;
pullTextView.setVisibility(View.VISIBLE);
pullTextView.setText("刷新中...");
onRefreshListener.onRefresh();
}
break;
case REFRESHCOMPLETE:
state = State.PULL_TO_REFRESH;
pullTextView.setText("下拉刷新");
resetHeader();
break;
}
}
/**
* 设置下拉head距离顶部的高度
*/
private void margeTop(){
MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) headerView.getLayoutParams();
mlp.topMargin = currentHeight;
headerView.setLayoutParams(mlp);
if (currentHeight > -10 && state != State.RELEASE_TO_REFRESH) {
state = State.RELEASE_TO_REFRESH;
pullTextView.setText("松手刷新");
}else if (currentHeight < -10 && state != State.PULL_TO_REFRESH) {
state = State.PULL_TO_REFRESH;
pullTextView.setText("下拉刷新");
}
}
/**
* 初始化下拉head的高度
*/
private void resetHeader(){
MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) headerView.getLayoutParams();
mlp.topMargin = -initHeight;
currentHeight = -initHeight;
headerView.setLayoutParams(mlp);
}
/**
* 实现刷新过程的回调接口
*/
private OnRefreshListener onRefreshListener; public void setOnRefreshListener(OnRefreshListener onRefreshListener){
this.onRefreshListener = onRefreshListener;
}
public interface OnRefreshListener{
public void onRefresh();
}
/**
* 刷新完成调用
*/
public void onRefreshComplete(){
setState(State.REFRESHCOMPLETE);
} }

适配器adater,这个很简陋,主要是辅助测试

package com.jwzhangjie.mypullrefresh;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; public class MyAdapter extends BaseAdapter{ private LayoutInflater mInflater;
public MyAdapter(Context context){
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return 19;
} @Override
public Object getItem(int position) {
return null;
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_listview, null);
textView = (TextView)convertView.findViewById(R.id.item_test);
convertView.setTag(textView);
}else {
textView = (TextView)convertView.getTag();
}
textView.setText("测试数据:"+position);
return convertView;
} }

然后就是Activity的调用:

package com.jwzhangjie.mypullrefresh;

import com.jwzhangjie.mypullrefresh.PullReFreshLibrary.OnRefreshListener;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.app.Activity; public class MainActivity extends Activity { private MyAdapter myAdapter;
private PullReFreshLibrary listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myAdapter = new MyAdapter(this);
listView = (PullReFreshLibrary)findViewById(R.id.testpull);
listView.setAdapter(myAdapter);
listView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
handler.sendEmptyMessageDelayed(1, 4000);
}
});
}
@SuppressLint("HandlerLeak")
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
listView.onRefreshComplete();
} };
}

我里面的布局也都很简单,

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <com.jwzhangjie.mypullrefresh.PullReFreshLibrary
android:id="@+id/testpull"
android:layout_width="match_parent"
android:layout_height="match_parent"
></com.jwzhangjie.mypullrefresh.PullReFreshLibrary> </LinearLayout>

headview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<RelativeLayout
android:id="@+id/testHeader"
android:layout_width="match_parent"
android:layout_height="300dip"
android:layout_marginTop="-48dip"
android:background="@drawable/main_photo2"
>
<LinearLayout
android:id="@+id/ptr_id_textwrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dip"
android:background="@drawable/refresh_text_bg"
>
<TextView
android:id="@+id/pullTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="20dip"
android:paddingRight="20dip"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:textSize="12sp"
android:textColor="#FFFFFFFF"
android:layout_gravity="center"
android:text="测试刷新"
/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>

item_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <TextView
android:id="@+id/item_test"
android:layout_width="match_parent"
android:layout_height="40dip"
/>
</LinearLayout>
 <dimen name="init_height">48dip</dimen>
<dimen name="header_view_height">300dip</dimen>

Android自定义下拉刷新的更多相关文章

  1. Android 自定义下拉刷新ListView

    package com.dwtedx.qq.view; import android.content.Context; import android.util.AttributeSet; import ...

  2. Android PullToRrefresh 自定义下拉刷新动画 (listview、scrollview等)

    PullToRefreshScrollView 自定义下拉刷新动画,只需改一处. 以下部分转载自http://blog.csdn.net/superjunjin/article/details/450 ...

  3. Xamarin. Android实现下拉刷新功能

    PS:发现文章被其他网站或者博客抓取后发表为原创了,给图片加了个水印 下拉刷新功能在安卓和iOS中非常常见,一般实现这样的功能都是直接使用第三方的库,网上能找到很多这样的开源库.然而在Xamarin. ...

  4. Android 定制下拉刷新头部 Ultra Pull To Refresh

    我们看到手机中的各种APP的花样繁多的下拉刷新是不是有点心动呢,想着自己定制自己的专门的下拉刷新,市场上比如,58同城,京东,天猫,美团等下拉刷新都是在下拉头部执行帧动画,我最近看到一个APP,就是慕 ...

  5. Android智能下拉刷新加载框架—看这些就够了

    一些值得学习的几个下拉刷新上拉加载开源库 Android智能下拉刷新框架-SmartRefreshLayout 支持所有的 View(AbsListView.RecyclerView.WebView. ...

  6. 自定义下拉刷新上拉加载View

    MainActivity.java package com.heima52.pullrefresh; import java.util.ArrayList; import com.heima52.pu ...

  7. 使用MJRefresh自定义下拉刷新,上拉加载动画

    有时候我们需要自己设置下拉刷新,上拉加载动画的实现,这里主要是记录下使用MJRefresh自定义下拉刷新,上拉加载动画..... 下拉刷新我们只需要继承MJRefreshGifHeader即可: 实现 ...

  8. android官方下拉刷新控件SwipeRefreshLayout的使用

    可能开发安卓的人大多数都用过很多下拉刷新的开源组件,但是今天用了官方v4支持包的SwipeRefreshLayout觉得效果也蛮不错的,特拿出来分享. 简介:SwipeRefreshLayout组件只 ...

  9. 使用 CSS overscroll-behavior 控制滚动行为:自定义下拉刷新和溢出效果

    CSS 的新属性 overscroll-behavior 允许开发者覆盖默认的浏览器滚动行为,一般用在滚动到顶部或者底部. 背景 滚动边界和滚动链接(boundary & chaining) ...

随机推荐

  1. CF196 D2 D

    Book of Evil,有一颗树,n个节点,有m个节点被标记,问n个节点中,有多少个节点,这些节点与这m个节点的最远的距离小于等于d. 用down[i], up[i]分别标记只考虑以i为root的子 ...

  2. 让ie6支持fixed最简单和实用的方法

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  3. UPC 2224 Boring Counting ★(山东省第四届ACM程序设计竞赛 tag:线段树)

    [题意]给定一个长度为N的数列,M个询问区间[L,R]内大于等于A小于等于B的数的个数. [题目链接]http://acm.upc.edu.cn/problem.php?id=2224 省赛的时候脑抽 ...

  4. 【转】UIColor对颜色的自定义

    原文网址:http://blog.sina.com.cn/s/blog_5f19ccb10101bhqh.html 在iOS开发中,我们使用UIColor来对我们的界面进行颜色设置,一般我们通过以下两 ...

  5. Java集合类:AbstractCollection源码解析

    一.Collection接口 从<Java集合:整体结构>一文中我们知道所有的List和Set都继承自Collection接口,该接口类提供了集合最基本的方法,虽然List接口和Set等都 ...

  6. 新手!SDK Manager里找不到API安装的选项怎么办?

    只有Tools和EXTRAS文件夹的选项,没有API包安装,咋办呢?   回复讨论(解决方案) 网络有问题吗? 网络有问题吗? 就是不知道啊 你是在eclispe里面打开的?还是在外面直接打开的?没有 ...

  7. 第一个MVC模式的程序

    数据库 是一个SQL sever数据库,结构很简单,创建名为firstMVC的数据库,只包含一个数据表(名称为Persons),其中共有三列,分别用于保存人员(persons)的ID.姓名以及创建日期 ...

  8. 将你的Asp.NET应用程序嵌入到SharePoint

    转:http://www.cnblogs.com/Clank/archive/2007/05/21/754073.html 为什么要将Asp.net应用程序嵌入到SharePoint?这个我们不讨论! ...

  9. 再见WCF

    转眼微软的WCF已走过十个年头,它是微软通信框架的集大成者,将之前微软所有的通信框架进行了整合,提供了统一的应用方式.记得从自己最开始做MFC时,就使用过Named Pipe命名管道,之后做Winfo ...

  10. MySQL table_id原理及风险分析

    1. 什么是table_id MySQL binlog文件按格式分为文件头部和事件信息.文件头部占4字节,内容固定为:"\xfe\x62\x69\x6e",接下来就是各个event ...