欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android新浪微博下拉刷新(最新消息显示在最上面)

程序员文章站 2023-11-20 17:36:40
查看最新消息要用到类似新浪微博下拉刷新 功能!把最新的消息显示在最上面! 代码如下: pulltorefreshlistview类代码 复制代码 代码如下: package...
查看最新消息要用到类似新浪微博下拉刷新 功能!把最新的消息显示在最上面!
代码如下:
pulltorefreshlistview类代码
复制代码 代码如下:

package com.markupartist.android.widget;

import java.util.date;
import com.markupartist.android.example.pulltorefresh.r;
import android.content.context;
import android.util.attributeset;
import android.util.log;
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.abslistview.onscrolllistener;
import android.widget.baseadapter;
import android.widget.imageview;
import android.widget.linearlayout;
import android.widget.listview;
import android.widget.progressbar;
import android.widget.textview;

public class pulltorefreshlistview extends listview implements onscrolllistener {
private static final string tag = "listview";
private final static int release_to_refresh = 0;
private final static int pull_to_refresh = 1;
private final static int refreshing = 2;
private final static int done = 3;
private final static int loading = 4;
// 实际的padding的距离与界面上偏移距离的比例
private final static int ratio = 3;
private layoutinflater inflater;
private linearlayout headview;
private textview tipstextview;
private textview lastupdatedtextview;
private imageview arrowimageview;
private progressbar progressbar;

private rotateanimation animation;
private rotateanimation reverseanimation;
// 用于保证starty的值在一个完整的touch事件中只被记录一次
private boolean isrecored;
private int headcontentwidth;
private int headcontentheight;
private int starty;
private int firstitemindex;
private int state;
private boolean isback;
private onrefreshlistener refreshlistener;
private boolean isrefreshable;
public pulltorefreshlistview(context context) {
super(context);
init(context);
}
public pulltorefreshlistview(context context, attributeset attrs) {
super(context, attrs);
init(context);
}
private void init(context context) {
setcachecolorhint(context.getresources().getcolor(android.r.color.transparent));
inflater = layoutinflater.from(context);
headview = (linearlayout) inflater.inflate(r.layout.pull_to_refresh_header, null);
arrowimageview = (imageview) headview
.findviewbyid(r.id.head_arrowimageview);
arrowimageview.setminimumwidth(70);
arrowimageview.setminimumheight(50);
progressbar = (progressbar) headview
.findviewbyid(r.id.head_progressbar);
tipstextview = (textview) headview.findviewbyid(r.id.head_tipstextview);
lastupdatedtextview = (textview) headview
.findviewbyid(r.id.head_lastupdatedtextview);
measureview(headview);
headcontentheight = headview.getmeasuredheight();
headcontentwidth = headview.getmeasuredwidth();
headview.setpadding(0, -1 * headcontentheight, 0, 0);
headview.invalidate();
log.v("size", "width:" + headcontentwidth + " height:"
+ headcontentheight);
addheaderview(headview, null, false);
setonscrolllistener(this);
animation = new rotateanimation(0, -180,
rotateanimation.relative_to_self, 0.5f,
rotateanimation.relative_to_self, 0.5f);
animation.setinterpolator(new linearinterpolator());
animation.setduration(250);
animation.setfillafter(true);
reverseanimation = new rotateanimation(-180, 0,
rotateanimation.relative_to_self, 0.5f,
rotateanimation.relative_to_self, 0.5f);
reverseanimation.setinterpolator(new linearinterpolator());
reverseanimation.setduration(200);
reverseanimation.setfillafter(true);
state = done;
isrefreshable = false;
}
public void onscroll(abslistview arg0, int firstvisiableitem, int arg2,
int arg3) {
firstitemindex = firstvisiableitem;
}
public void onscrollstatechanged(abslistview arg0, int arg1) {
}
public boolean ontouchevent(motionevent event) {

firstitemindex=getfirstvisibleposition();
if (isrefreshable) {
switch (event.getaction()) {
case motionevent.action_down:
if (firstitemindex == 0 && !isrecored) {
isrecored = true;
starty = (int) event.gety();
log.v(tag, "在down时候记录当前位置‘");
}
break;
case motionevent.action_up:
if (state != refreshing && state != loading) {
if (state == done) {
// 什么都不做
}
if (state == pull_to_refresh) {
state = done;
changeheaderviewbystate();
log.v(tag, "由下拉刷新状态,到done状态");
}
if (state == release_to_refresh) {
state = refreshing;
changeheaderviewbystate();
onrefresh();
log.v(tag, "由松开刷新状态,到done状态");
}
}
isrecored = false;
isback = false;
break;
case motionevent.action_move:
int tempy = (int) event.gety();
if (!isrecored && firstitemindex == 0) {
log.v(tag, "在move时候记录下位置");
isrecored = true;
starty = tempy;
}
if (state != refreshing && isrecored && state != loading) {
// 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
// 可以松手去刷新了
if (state == release_to_refresh) {
setselection(0);
// 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
if (((tempy - starty) / ratio < headcontentheight)
&& (tempy - starty) > 0) {
state = pull_to_refresh;
changeheaderviewbystate();
log.v(tag, "由松开刷新状态转变到下拉刷新状态");
}
// 一下子推到顶了
else if (tempy - starty <= 0) {
state = done;
changeheaderviewbystate();
log.v(tag, "由松开刷新状态转变到done状态");
}
// 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
else {
// 不用进行特别的操作,只用更新paddingtop的值就行了
}
}
// 还没有到达显示松开刷新的时候,done或者是pull_to_refresh状态
if (state == pull_to_refresh) {
setselection(0);
// 下拉到可以进入release_to_refresh的状态
if ((tempy - starty) / ratio >= headcontentheight) {
state = release_to_refresh;
isback = true;
changeheaderviewbystate();
log.v(tag, "由done或者下拉刷新状态转变到松开刷新");
}
// 上推到顶了
else if (tempy - starty <= 0) {
state = done;
changeheaderviewbystate();
log.v(tag, "由done或者下拉刷新状态转变到done状态");
}
}
// done状态下
if (state == done) {
if (tempy - starty > 0) {
state = pull_to_refresh;
changeheaderviewbystate();
}
}
// 更新headview的size
if (state == pull_to_refresh) {
headview.setpadding(0, -1 * headcontentheight
+ (tempy - starty) / ratio, 0, 0);
}
// 更新headview的paddingtop
if (state == release_to_refresh) {
headview.setpadding(0, (tempy - starty) / ratio
- headcontentheight, 0, 0);
}
}
break;
}
}
return super.ontouchevent(event);
}
// 当状态改变时候,调用该方法,以更新界面
private void changeheaderviewbystate() {
switch (state) {
case release_to_refresh:
arrowimageview.setvisibility(view.visible);
progressbar.setvisibility(view.gone);
tipstextview.setvisibility(view.visible);
lastupdatedtextview.setvisibility(view.visible);
arrowimageview.clearanimation();
arrowimageview.startanimation(animation);
tipstextview.settext("松开刷新");
log.v(tag, "当前状态,松开刷新");
break;
case pull_to_refresh:
progressbar.setvisibility(view.gone);
tipstextview.setvisibility(view.visible);
lastupdatedtextview.setvisibility(view.visible);
arrowimageview.clearanimation();
arrowimageview.setvisibility(view.visible);
// 是由release_to_refresh状态转变来的
if (isback) {
isback = false;
arrowimageview.clearanimation();
arrowimageview.startanimation(reverseanimation);
tipstextview.settext("下拉刷新");
} else {
tipstextview.settext("下拉刷新");
}
log.v(tag, "当前状态,下拉刷新");
break;
case refreshing:
headview.setpadding(0, 0, 0, 0);
progressbar.setvisibility(view.visible);
arrowimageview.clearanimation();
arrowimageview.setvisibility(view.gone);
tipstextview.settext("正在刷新...");
lastupdatedtextview.setvisibility(view.visible);
log.v(tag, "当前状态,正在刷新...");
break;
case done:
headview.setpadding(0, -1 * headcontentheight, 0, 0);
progressbar.setvisibility(view.gone);
arrowimageview.clearanimation();
arrowimageview.setimageresource(r.drawable.ic_pulltorefresh_arrow);
tipstextview.settext("下拉刷新");
lastupdatedtextview.setvisibility(view.visible);
log.v(tag, "当前状态,done");
break;
}
}
public void setonrefreshlistener(onrefreshlistener refreshlistener) {
this.refreshlistener = refreshlistener;
isrefreshable = true;
}
public interface onrefreshlistener {
public void onrefresh();
}
public void onrefreshcomplete() {
state = done;
lastupdatedtextview.settext("最近更新:" + new date().tolocalestring());
changeheaderviewbystate();
}
private void onrefresh() {
if (refreshlistener != null) {
refreshlistener.onrefresh();
}
}
// 此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headview的width以及height
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(0, 0 + 0, p.width);
int lpheight = p.height;
int childheightspec;
if (lpheight > 0) {
childheightspec = measurespec.makemeasurespec(lpheight,
measurespec.exactly);
} else {
childheightspec = measurespec.makemeasurespec(0,
measurespec.unspecified);
}
child.measure(childwidthspec, childheightspec);
}
public void setadapter(baseadapter adapter) {
lastupdatedtextview.settext("最近更新:" + new date().tolocalestring());
super.setadapter(adapter);
}
}

activity调用代码
复制代码 代码如下:

package com.markupartist.android.example.pulltorefresh;
import java.util.arrays;
import java.util.linkedlist;
import android.app.listactivity;
import android.os.asynctask;
import android.os.bundle;
import android.widget.arrayadapter;
import com.markupartist.android.widget.pulltorefreshlistview;
import com.markupartist.android.widget.pulltorefreshlistview.onrefreshlistener;
public class pulltorefreshactivity extends listactivity {
private linkedlist<string> mlistitems;
/** called when the activity is first created. */
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.pull_to_refresh);
// set a listener to be invoked when the list should be refreshed.
((pulltorefreshlistview) getlistview()).setonrefreshlistener(new onrefreshlistener() {
@override
public void onrefresh() {
// do work to refresh the list here.
new getdatatask().execute();
}
});
mlistitems = new linkedlist<string>();
mlistitems.addall(arrays.aslist(mstrings));
arrayadapter<string> adapter = new arrayadapter<string>(this,
android.r.layout.simple_list_item_1, mlistitems);
setlistadapter(adapter);
}
private class getdatatask extends asynctask<void, void, string[]> {
@override
protected string[] doinbackground(void... params) {
// simulates a background job.
try {
thread.sleep(2000);
} catch (interruptedexception e) {

}
return mstrings;
}
@override
protected void onpostexecute(string[] result) {
mlistitems.addfirst("added after refresh...");
// call onrefreshcomplete when the list has been refreshed.
((pulltorefreshlistview) getlistview()).onrefreshcomplete();
super.onpostexecute(result);
}
}
private string[] mstrings = {
// "abbaye de belloc", "abbaye du mont des cats", "abertam",
// "abondance", "ackawi", "acorn", "adelost", "affidelice au chablis",
"afuega'l pitu", "airag", "airedale", "aisy cendre",
"allgauer emmentaler"};
}