Android自定义下拉刷新
网上的下拉刷新功能很多,不过基本上都是隐藏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自定义下拉刷新的更多相关文章
- Android 自定义下拉刷新ListView
package com.dwtedx.qq.view; import android.content.Context; import android.util.AttributeSet; import ...
- Android PullToRrefresh 自定义下拉刷新动画 (listview、scrollview等)
PullToRefreshScrollView 自定义下拉刷新动画,只需改一处. 以下部分转载自http://blog.csdn.net/superjunjin/article/details/450 ...
- Xamarin. Android实现下拉刷新功能
PS:发现文章被其他网站或者博客抓取后发表为原创了,给图片加了个水印 下拉刷新功能在安卓和iOS中非常常见,一般实现这样的功能都是直接使用第三方的库,网上能找到很多这样的开源库.然而在Xamarin. ...
- Android 定制下拉刷新头部 Ultra Pull To Refresh
我们看到手机中的各种APP的花样繁多的下拉刷新是不是有点心动呢,想着自己定制自己的专门的下拉刷新,市场上比如,58同城,京东,天猫,美团等下拉刷新都是在下拉头部执行帧动画,我最近看到一个APP,就是慕 ...
- Android智能下拉刷新加载框架—看这些就够了
一些值得学习的几个下拉刷新上拉加载开源库 Android智能下拉刷新框架-SmartRefreshLayout 支持所有的 View(AbsListView.RecyclerView.WebView. ...
- 自定义下拉刷新上拉加载View
MainActivity.java package com.heima52.pullrefresh; import java.util.ArrayList; import com.heima52.pu ...
- 使用MJRefresh自定义下拉刷新,上拉加载动画
有时候我们需要自己设置下拉刷新,上拉加载动画的实现,这里主要是记录下使用MJRefresh自定义下拉刷新,上拉加载动画..... 下拉刷新我们只需要继承MJRefreshGifHeader即可: 实现 ...
- android官方下拉刷新控件SwipeRefreshLayout的使用
可能开发安卓的人大多数都用过很多下拉刷新的开源组件,但是今天用了官方v4支持包的SwipeRefreshLayout觉得效果也蛮不错的,特拿出来分享. 简介:SwipeRefreshLayout组件只 ...
- 使用 CSS overscroll-behavior 控制滚动行为:自定义下拉刷新和溢出效果
CSS 的新属性 overscroll-behavior 允许开发者覆盖默认的浏览器滚动行为,一般用在滚动到顶部或者底部. 背景 滚动边界和滚动链接(boundary & chaining) ...
随机推荐
- AC题目简解-dp
dp类:A - Bridging signals ZOJ 3627 POJ1631 HDU1950给出一个从1-n的数字排列,求最长上升子序列长度.直接说解法吧.新开一个数组d,d[i]表示的是能构成 ...
- 1494. Monobilliards(栈)
1494 之前记得数据结构试卷上有这种题 就是判断某一出栈顺序 是不是满足以1.2...n为入栈顺序 a1,a2,a3..an; 对于任意相邻a[i],a[i+1] 如果a[i]>a[i+1]+ ...
- 结构体 typedef struct hash_cell_struct hash_cell_t;
typedef struct hash_cell_struct hash_cell_t; struct hash_cell_struct{ void* node; /*!< hash chain ...
- 陈正冲老师讲c语言之const关键字
1.const 关键字也许该被替换为 readolny const是constant的缩写,是恒定不变的意思,也翻译为常量.常数等.很不幸,正是因为这一点,很多人都认为被const修饰的值是常量.这是 ...
- [html5] (Notification) 桌面通知
前几天要做一个桌面通知的功能,翻查以前做的笔记,发现webkitNotifications这个已经不能用了,baidu了下,基本都是介绍webkitNotifications的,后来在SOF上找到答案 ...
- asp.net微信公众平台开发
http://mp.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E6%8E%A5%E5%8F%A3%E6%8C%87%E5%8D%97 ...
- expunge
expunge 擦掉: 除去: 删去: 消除 1. The experience was something he had tried to expunge from his memory. 他曾努力 ...
- SQL Server 外键约束的例子
外键约束的测试表与测试数据 -- 创建测试主表. ID 是主键. CREATE TABLE test_main ( id INT, value ), PRIMARY KEY(id) ); -- 创建测 ...
- 《Python基础教程(第二版)》学习笔记 -> 第二章 列表和元组
本章将引入一个新的概念:数据结构. 数据结构是通过某种方式阻止在一起的数据元素的集合,这些数据元素可以是数字或者字符,设置可以是其他数据结构. Python中,最基本的数据结构是序列(Sequence ...
- Open-Drain V.S. Push-Pull
作者:crifan (http://bbs.chinaunix.net)邮箱:green-waste@163.com [Open-Drain与Push-Pull]GPIO的功能,简单说就是可以根据自己 ...