android Pull-to-refresh 动画实现
现在很多应用都使用的pull-to-refresh 动画效果,包括微博、微信、QQ等。
这里示例性的实现pull-to-refresh 动画效果,并增加了额外的图片放大、透明度、位移等动画。这些动画也被经常使用。
实现效果:
http://v.youku.com/v_show/id_XNjY0MTQzODQ4.html
java文件
package com.buptfarmer.devapp;
import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.view.ViewHelper;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.View.OnTouchListener;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class PullAnimationExample extends Activity {
private TextView mRefreshText;
private TextView mAaaText;
private ImageView mHeaderImg;
private LinearLayout mBottom;
private LinearLayout mHolder;
private int mCount;
private RotateAnimation mFlipAnimation;
private RotateAnimation mReverseFlipAnimation;
private int mSlop;
private boolean mSwiping;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewConfiguration vc = ViewConfiguration.get(this);
mSlop = vc.getScaledTouchSlop();
initView();
mFlipAnimation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mFlipAnimation.setFillAfter(true);
mReverseFlipAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
mReverseFlipAnimation.setFillAfter(true);
}
private void initView() {
setContentView(R.layout.pull_animation_example);
mHolder = (LinearLayout) findViewById(R.id.holder);
mHeaderImg = (ImageView) findViewById(R.id.header_img);
ViewHelper.setAlpha(mHeaderImg, 0.3f);
mRefreshText = (TextView)findViewById(R.id.refresh);
mRefreshText.setVisibility(View.INVISIBLE);
mAaaText = (TextView) findViewById(R.id.aaa);
mBbbText = (TextView) findViewById(R.id.bbb);
mBottom = (LinearLayout) findViewById(R.id.buttom);
mHolder.setOnTouchListener(new OnTouchListener() {
private float mDownX;
private float mDownY;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mDownX = event.getX();
mDownY = event.getY();
mRefreshText.setVisibility(View.VISIBLE);
mRefreshText.setText("pull to refresh");
break;
}
case MotionEvent.ACTION_MOVE: {
float deltaX = Math.abs(event.getX() - mDownX);
float deltaY = Math.abs(event.getY() - mDownY);
if (deltaY > mSlop && deltaY > 0) {
mSwiping = true;
v.getParent().requestDisallowInterceptTouchEvent(true);
float percent = Math.min(0.2f, Math.abs(deltaY) / mHeaderImg.getMeasuredHeight());
ViewHelper.setScaleX(mHeaderImg,
1f + 3f * percent);
ViewHelper.setScaleY(mHeaderImg,
1f + 3f * percent);
ViewHelper.setAlpha(mHeaderImg,
Math.min(1f, 0.3f+3f * percent));
ViewHelper.setTranslationY(mBottom, deltaY);
if(deltaY > mRefreshText.getHeight()){
mRefreshText.setText("release to refresh");
}
}
break;
}
case MotionEvent.ACTION_UP: {
if (mSwiping) {
mSwiping = false;
ViewHelper.setScaleX(mHeaderImg, 1f);
ViewHelper.setScaleY(mHeaderImg, 1f);
ViewHelper.setAlpha(mHeaderImg, 0.3f);
animate(mHeaderImg).alpha(0.3f).scaleX(1f).scaleY(1f).setListener(null);
animate(mBottom).translationY(0).setListener(null);
updateText();
mRefreshText.setVisibility(View.INVISIBLE);
mRefreshText.setText("refreshing...");
}
break;
}
default: {
break;
}
}
return true;
}
});
}
private void updateText() {
animateText(mAaaText, new AnimationCallback() {
@Override
public void onAnimation() {
// TODO Auto-generated method stub
mAaaText.setText("update " + mCount++);
}
});
}
public static void animateText(final View view, final AnimationCallback callback) {
int origHeight = view.getHeight();
animate(view).translationY(origHeight).alpha(0).scaleX(0.5f).scaleY(0.5f)
.setListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
if (callback != null) {
callback.onAnimation();
}
animate(view).translationY(0).alpha(1).scaleX(1f).scaleY(1f).setListener(null);
};
});
}
public interface AnimationCallback {
public void onAnimation();
}
}
layout xml 文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="@+id/header_img"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="@drawable/all_in_one" />
<TextView
android:id="@+id/refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="pull to refresh"
android:textColor="@color/blue"
android:textSize="20sp" />
<TextView
android:id="@+id/aaa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/refresh"
android:layout_centerHorizontal="true"
android:text="aaaaaa text"
android:textColor="@color/red"
android:textSize="20sp" />
<LinearLayout
android:id="@+id/buttom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/header_img"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:id="@+id/bbb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bbbbbb text"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bbbbbb text"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bbbbbb text"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bbbbbb text"
android:textSize="20sp" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>