您的位置:首页 > 其它

使用ScrollView实现下拉刷新(一)

2015-06-19 23:26 405 查看
转载自:http://blog.csdn.net/a6920502/article/details/8759244

使用ListView来做下拉刷新有很多例子,而且封装的很好。

ListView有 header 但是如果不使用ListView的下拉刷新网上的例子相对来说比较少,于是自己动手写了个,原理差不多,主要都是在OnTouchListener

首先是Header的布局文件:

[html] view
plaincopy

<?xml version="1.0" encoding="utf-8"?>

<!-- ListView的头部 -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/head_rootLayout"

android:layout_width="fill_parent"

&nb
4000
sp; android:layout_height="wrap_content" >

<!-- 内容 -->

<RelativeLayout

android:id="@+id/head_contentLayout"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:paddingLeft="30dp" >

<!-- 箭头图像、进度条 -->

<FrameLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_centerVertical="true" >

<!-- 箭头 -->

<ImageView

android:id="@+id/head_arrowImageView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:contentDescription="@string/app_name"

android:src="@drawable/head_arrow" />

<!-- 进度条 -->

<ProgressBar

android:id="@+id/head_progressBar"

style="?android:attr/progressBarStyleSmall"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:visibility="gone" />

</FrameLayout>

<!-- 提示、最近更新 -->

<LinearLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true"

android:gravity="center_horizontal"

android:orientation="vertical" >

<!-- 提示 -->

<TextView

android:id="@+id/head_tipsTextView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/pulltorefresh"

android:textSize="20sp" />

<!-- 最近更新 -->

<TextView

android:id="@+id/head_lastUpdatedTextView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/lastupdate"

android:textColor="#cc6600"

android:textSize="12sp" />

</LinearLayout>

</RelativeLayout>

</LinearLayout>

Activity布局:

[html] view
plaincopy

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"

android:id="@+id/globleLayout">

<ScrollView

android:id="@+id/scrollView"

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<span style="white-space:pre"> </span><!-- 这里放你想要放的布局 --!>

<LinearLayout

android:id="@+id/linearLayout"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >

<ImageView

android:layout_width="80dp"

android:layout_height="120dp"

android:src="@drawable/a" />

<ImageView

android:layout_width="80dp"

android:layout_height="120dp"

android:src="@drawable/b" />

<ImageView

android:layout_width="80dp"

android:layout_height="120dp"

android:src="@drawable/c" />

<ImageView

android:layout_width="80dp"

android:layout_height="120dp"

android:src="@drawable/d" />

<ImageView

android:layout_width="80dp"

android:layout_height="120dp"

android:src="@drawable/e" />

<ImageView

android:layout_width="80dp"

android:layout_height="120dp"

android:src="@drawable/f" />

</LinearLayout>

</ScrollView>

</LinearLayout>

现在是Activity 的代码:

[java] view
plaincopy

package com.example.scrollviewtest;

import java.util.Date;

import android.app.Activity;

import android.content.Context;

import android.os.AsyncTask;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.MeasureSpec;

import android.view.View.OnTouchListener;

import android.view.ViewGroup;

import android.view.ViewGroup.LayoutParams;

import android.view.animation.LinearInterpolator;

import android.view.animation.RotateAnimation;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.ProgressBar;

import android.widget.ScrollView;

import android.widget.TextView;

public class MainActivity extends Activity {

private ScrollView sc;

private LinearLayout header;

private ImageView arrowImg;

private ProgressBar headProgress;

private TextView lastUpdateTxt;

private TextView tipsTxt;

private RotateAnimation tipsAnimation;

private RotateAnimation reverseAnimation;

private LayoutInflater inflater;

private LinearLayout globleLayout;

private int headerHeight; //头高度

private int lastHeaderPadding; //最后一次调用Move Header的Padding

private boolean isBack; //从Release 转到 pull

private int headerState = DONE;

static final private int RELEASE_To_REFRESH = 0;

static final private int PULL_To_REFRESH = 1;

static final private int REFRESHING = 2;

static final private int DONE = 3;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

init(this);

}

private void init(Context context) {

globleLayout = (LinearLayout) findViewById(R.id.globleLayout);

sc = (ScrollView) globleLayout.findViewById(R.id.scrollView);

inflater = (LayoutInflater) this

.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

header = (LinearLayout) inflater.inflate(R.layout.drag_drop_header, null);

measureView(header);

headerHeight = header.getMeasuredHeight();

lastHeaderPadding = (-1*headerHeight); //最后一次调用Move Header的Padding

header.setPadding(0, lastHeaderPadding, 0, 0);

header.invalidate();

globleLayout.addView(header,0);

headProgress = (ProgressBar) findViewById(R.id.head_progressBar);

arrowImg = (ImageView) findViewById(R.id.head_arrowImageView);

arrowImg.setMinimumHeight(50);

arrowImg.setMinimumWidth(50);

tipsTxt = (TextView) findViewById(R.id.head_tipsTextView);

lastUpdateTxt = (TextView) findViewById(R.id.head_lastUpdatedTextView);

//箭头转动动画

tipsAnimation = new RotateAnimation(0, -180,

RotateAnimation.RELATIVE_TO_SELF, 0.5f,

RotateAnimation.RELATIVE_TO_SELF, 0.5f);

tipsAnimation.setInterpolator(new LinearInterpolator());

tipsAnimation.setDuration(200); //动画持续时间

tipsAnimation.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);

//为scrollview绑定事件

sc.setOnTouchListener(new OnTouchListener() {

private int beginY;

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_MOVE:

//sc.getScrollY == 0 scrollview 滑动到头了

//lastHeaderPadding > (-1*headerHeight) 表示header还没完全隐藏起来时

//headerState != REFRESHING 当正在刷新时

if((sc.getScrollY() == 0 || lastHeaderPadding > (-1*headerHeight)) && headerState != REFRESHING) {

//拿到滑动的Y轴距离

int interval = (int) (event.getY() - beginY);

//是向下滑动而不是向上滑动

if (interval > 0) {

interval = interval/2;//下滑阻力

lastHeaderPadding = interval + (-1*headerHeight);

header.setPadding(0, lastHeaderPadding, 0, 0);

if(lastHeaderPadding > 0) {

//txView.setText("我要刷新咯");

headerState = RELEASE_To_REFRESH;

//是否已经更新了UI

if(! isBack) {

isBack = true; //到了Release状态,如果往回滑动到了pull则启动动画

changeHeaderViewByState();

}

} else {

headerState = PULL_To_REFRESH;

changeHeaderViewByState();

//txView.setText("看到我了哦");

//sc.scrollTo(0, headerPadding);

}

}

}

break;

case MotionEvent.ACTION_DOWN:

//加上下滑阻力与实际滑动距离的差(大概值)

beginY = (int) ((int) event.getY() + sc.getScrollY()*1.5);

break;

case MotionEvent.ACTION_UP:

if (headerState != REFRESHING) {

switch (headerState) {

case DONE:

//什么也不干

break;

case PULL_To_REFRESH:

headerState = DONE;

lastHeaderPadding = -1*headerHeight;

header.setPadding(0, lastHeaderPadding, 0, 0);

changeHeaderViewByState();

break;

case RELEASE_To_REFRESH:

isBack = false; //准备开始刷新,此时将不会往回滑动

headerState = REFRESHING;

changeHeaderViewByState();

onRefresh();

break;

default:

break;

}

}

break;

}

//如果Header是完全被隐藏的则让ScrollView正常滑动,让事件继续否则的话就阻断事件

if(lastHeaderPadding > (-1*headerHeight) && headerState != REFRESHING) {

return true;

} else {

return false;

}

}

});

}

private void changeHeaderViewByState() {

switch (headerState) {

case PULL_To_REFRESH:

// 是由RELEASE_To_REFRESH状态转变来的

if (isBack) {

isBack = false;

arrowImg.startAnimation(reverseAnimation);

tipsTxt.setText("下拉刷新");

}

tipsTxt.setText("下拉刷新");

break;

case RELEASE_To_REFRESH:

arrowImg.setVisibility(View.VISIBLE);

headProgress.setVisibility(View.GONE);

tipsTxt.setVisibility(View.VISIBLE);

lastUpdateTxt.setVisibility(View.VISIBLE);

arrowImg.clearAnimation();

arrowImg.startAnimation(tipsAnimation);

tipsTxt.setText("松开刷新");

break;

case REFRESHING:

lastHeaderPadding = 0;

header.setPadding(0, lastHeaderPadding, 0, 0);

header.invalidate();

headProgress.setVisibility(View.VISIBLE);

arrowImg.clearAnimation();

arrowImg.setVisibility(View.INVISIBLE);

tipsTxt.setText("正在刷新...");

lastUpdateTxt.setVisibility(View.VISIBLE);

break;

case DONE:

lastHeaderPadding = -1 * headerHeight;

header.setPadding(0, lastHeaderPadding, 0, 0);

header.invalidate();

headProgress.setVisibility(View.GONE);

arrowImg.clearAnimation();

arrowImg.setVisibility(View.VISIBLE);

tipsTxt.setText("下拉刷新");

lastUpdateTxt.setVisibility(View.VISIBLE);

break;

default:

break;

}

}

private void onRefresh() {

new AsyncTask<Void, Void, Void>() {

protected Void doInBackground(Void... params) {

try {

Thread.sleep(2000);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

@Override

protected void onPostExecute(Void result) {

onRefreshComplete();

}

}.execute(null);

}

public void onRefreshComplete() {

headerState = DONE;

lastUpdateTxt.setText("最近更新:" + new Date().toLocaleString());

changeHeaderViewByState();

}

//由于OnCreate里面拿不到header的高度所以需要手动计算

private void measureView(View childView) {

LayoutParams p = childView.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 height = p.height;

int childHeightSpec;

if (height > 0) {

childHeightSpec = MeasureSpec.makeMeasureSpec(height,

MeasureSpec.EXACTLY);

} else {

childHeightSpec = MeasureSpec.makeMeasureSpec(0,

MeasureSpec.UNSPECIFIED);

}

childView.measure(childWidthSpec, childHeightSpec);

}

}<span style="color: rgb(255, 0, 0);">

</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: