网上的下拉刷新功能很多,不过基本上都是隐藏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. (转)详解LVS负载均衡之三种工作模型原理和10种调度算法

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://linuxnx.blog.51cto.com/6676498/1195379 LV ...

  2. uva11082 Matrix Decompressing

    网络流 首先算出每行每列的数的和. 每行的值减去c,每列的值减去R 然后每行和每列之间连边,容量为19. 这样一来,(i,j)的流量相当于(i,j)的值-1. 这样就避免了流量为0不对应答案的尴尬情况 ...

  3. Cacti 'graph_xport.php' SQL注入漏洞

    漏洞版本: Cacti < 0.8.8b 漏洞描述: Bugtraq ID:66555 Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具. Cact ...

  4. http://www.cnblogs.com/youfan/articles/3216816.html

    我对 CodeFirst 的理解,与之对应的有 ModelFirst与 DatabaseFirst ,三者各有千秋,依项目实际情况自行选择. 1.开发过程中先行设计数据库并依此在项目中生成 *.dbm ...

  5. 【jQuery日期处理】两个时间大小的比较

    function checkEndTime(){ var startTime=$("#startTime").val(); var start=new Date(startTime ...

  6. Spring 教程(一)

    一.Spring是什么 通常说的Spring其实指的是Spring Framework,它是Spring下的一个子项目,Spring围绕Spring Framework这个核心项目开发了大量其他项目, ...

  7. 用js将毫秒时间转成正常时间

    1. 将毫秒时间转成正常时间 //#region 将毫秒转换成正常的日期 function getDate(time) { var date = new Date(parseInt(time)); v ...

  8. Linux下配置Mysql允许远程访问

    操作非常简单,就5步骤,如下: 1.进入 mysql: ? 1 /usr/local/mysql/bin/mysql -u root -p 2.使用 mysql库 : ? 1 use mysql; 3 ...

  9. 【暑假】[深入动态规划]UVa 1412 Fund Management

    UVa 1412 Fund Management 题目: UVA - 1412 Fund Management Time Limit: 3000MS   Memory Limit: Unknown   ...

  10. POJ 1738 石子合并2 GarsiaWachs算法

    石子合并(GarsiaWachs算法) 只能用该算法过!!! 详解看代码 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~ ...