在github开源的众多下拉刷新中,自己比较喜欢的是android-Ultra-Pull-to-Refresh,动画效果做的比较好,于是决定研究下是怎么处理的
下面写了个比较简单的,比android-Ultra-Pull-to-Refresh要简单很多,没有什么扩展功能,仅仅为了学习,自己感觉动画做的蛮好
源码链接:点击打开链接
package cn.edu.sxu.www.customerpullrefresh;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;
/**
* Created by ${huozhenpeng} on 17/4/17.
* Company : www.miduo.com
*/
public class PtrFrameLayout extends ViewGroup {
public PtrFrameLayout(Context context) {
this(context,null);
}
public PtrFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs,-1);
}
public PtrFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
layoutChildren();
}
//当前偏移的距离
private int offset;
private void layoutChildren() {
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
if (headView != null) {
MarginLayoutParams lp = (MarginLayoutParams) headView.getLayoutParams();
final int left = paddingLeft + lp.leftMargin;
// enhance readability(header is layout above screen when first init)
final int top = -(mHeaderHeight - paddingTop - lp.topMargin - offset);
final int right = left + headView.getMeasuredWidth();
final int bottom = top + headView.getMeasuredHeight();
headView.layout(left, top, right, bottom);
}
if (contentView != null) {
MarginLayoutParams lp = (MarginLayoutParams) contentView.getLayoutParams();
final int left = paddingLeft + lp.leftMargin;
final int top = paddingTop + lp.topMargin + offset;
final int right = left + contentView.getMeasuredWidth();
final int bottom = top + contentView.getMeasuredHeight();
contentView.layout(left, top, right, bottom);
}
}
private void init()
{
mScrollChecker = new ScrollChecker();
}
private RelativeLayout headView;
private TextView contentView;
private ProgressBar pb_progress;
private TextView tv_title;
@Override
protected void onFinishInflate() {
super.onFinishInflate();
headView= (RelativeLayout) getChildAt(0);
pb_progress= (ProgressBar) headView.findViewById(R.id.pb_progress);
tv_title= (TextView) headView.findViewById(R.id.tv_title);
contentView= (TextView) getChildAt(1);
if (headView != null) {
headView.bringToFront();
}
}
private int mHeaderHeight;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (headView != null) {
measureChildWithMargins(headView, widthMeasureSpec, 0, heightMeasureSpec, 0);
MarginLayoutParams lp = (MarginLayoutParams) headView.getLayoutParams();
mHeaderHeight = headView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
}
if (contentView != null) {
measureContentView(contentView, widthMeasureSpec, heightMeasureSpec);
}
}
private void measureContentView(View child,
int parentWidthMeasureSpec,
int parentHeightMeasureSpec) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
getPaddingTop() + getPaddingBottom() + lp.topMargin, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
public static class LayoutParams extends MarginLayoutParams {
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
@SuppressWarnings({"unused"})
public LayoutParams(MarginLayoutParams source) {
super(source);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p != null && p instanceof LayoutParams;
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
public boolean dispatchTouchEventSupper(MotionEvent e) {
return super.dispatchTouchEvent(e);
}
private int Y;
private int curY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction())
{
case MotionEvent.ACTION_DOWN:
Y= (int) ev.getY();
return dispatchTouchEventSupper(ev);
case MotionEvent.ACTION_MOVE:
curY= (int) ev.getY();
headView.offsetTopAndBottom(curY-Y);
contentView.offsetTopAndBottom(curY-Y);
Y=curY;
return true;
case MotionEvent.ACTION_UP:
onRelease();
break;
}
return super.dispatchTouchEvent(ev);
}
//释放时,contentView的top值
private int releaseTop;
/**
* 假设每次让回复到250px的时候执行正在刷新操作
*/
private void onRelease()
{
releaseTop=contentView.getTop();
if(contentView.getTop()>=mHeaderHeight)
{
mScrollChecker.tryToScrollTo(releaseTop-250, 1000);
postDelayed(new Runnable() {
@Override
public void run() {
//刷新2s后恢复到初始位置
//不要用这个,getTop值恢复过程中会变化的
//mScrollChecker.tryToScrollTo(contentView.getTop()/2, 500);
mScrollChecker.tryToScrollTo(250, 1500);
}
},2000);
}
else
{
//相当于不执行刷新
mScrollChecker.tryToScrollTo(releaseTop, 1500);
}
}
private ScrollChecker mScrollChecker;
class ScrollChecker implements Runnable {
private Scroller mScroller;
public ScrollChecker() {
mScroller = new Scroller(getContext());
}
private int oldCurrY;
@Override
public void run() {
boolean finish = !mScroller.computeScrollOffset() || mScroller.isFinished();
if(!finish)
{
headView.offsetTopAndBottom(-mScroller.getCurrY()+oldCurrY);
contentView.offsetTopAndBottom(-mScroller.getCurrY()+oldCurrY);
oldCurrY=mScroller.getCurrY();
post(this);
}
}
public void tryToScrollTo(int to, int duration) {
oldCurrY=0;
mScroller.startScroll(0, 0, 0, to, duration);
post(this);
}
}
}
MainActivity类
package cn.edu.sxu.www.customerpullrefresh;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<cn.edu.sxu.www.customerpullrefresh.PtrFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="500px">
<TextView
android:id="@+id/tv_title"
android:background="#00ff00"
android:layout_width="match_parent"
android:layout_height="500px"
android:text="头部"
android:gravity="center"
android:textColor="#00aabb"
/>
<ProgressBar
android:id="@+id/pb_progress"
android:layout_width="wrap_content"
android:layout_height="250px"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
/>
</RelativeLayout>
<TextView
android:focusable="true"
android:clickable="true"
android:focusableInTouchMode="true"
android:background="#00aabb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="内容"
android:gravity="center"
/>
</cn.edu.sxu.www.customerpullrefresh.PtrFrameLayout>
</RelativeLayout>