import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
//需要ninesoldandroid.jar扩展包
import com.nineoldandroids.view.ViewHelper;
@SuppressLint("NewApi")
public class MainActivity extends Activity implements OnTouchListener {
private View view;
private float downY;
private float fingerRoll;
private float viewRoll;
private float viewY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = findViewById(R.id.view_top);
view.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int limit = 200;
switch (event.getAction()) {
// 获取手指按下时的坐标
case MotionEvent.ACTION_DOWN:
downY = event.getY();
break;
// 手指移动的过程中,消息列表跟随移动
case MotionEvent.ACTION_MOVE:
// 消息列表移动的距离=手指移动距离*0.5
fingerRoll = event.getY() - downY;
// 手指网上滑动,或者没有滑动距离
if (fingerRoll <= 0) {
break;
}
viewRoll = fingerRoll * 0.5f;
// 属性动画
// 跟用户操作相关联
ViewHelper.setTranslationY(view, viewRoll);
break;
case MotionEvent.ACTION_UP:
fingerRoll = event.getY() - downY;
// 手指网上滑动,或者没有滑动距离
if (fingerRoll <= 0) {
break;
}
viewRoll = fingerRoll * 0.5f;
// 记录下手指松开时,消息列表的Y坐标
viewY = view.getY();
if (viewRoll < limit) {
// 消息列表滑动的距离小于限定值,滑回去
// 否则,直接滑到底部(作业)
// 花了500毫秒完成了,0到500的过程
// 当值为250,动画完成的进度时,0.5
// 动画执行的进度,跟消息列表滑动的进度保持一致
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 500)
.setDuration(500);
// 开始动画
valueAnimator.start();
// 这个动画要完成,消息列表滑动到初始位置这个过程
valueAnimator
.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator va) {
// 执行进度
float rate = Float.parseFloat(va
.getAnimatedValue().toString()) / 500;
// 消息列表的y坐标=松开手指时消息列表的Y坐标+(动画进度*消息列表滑动的总距离)
// 2.2 解决setY
// 往上滑动,Y坐标变小
float y = viewY - (rate * viewRoll);
view.setY(y);
}
});
} else {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 500)
.setDuration(500);
// 开始动画
valueAnimator.start();
// 这个动画要完成,消息列表滑动到初始位置这个过程
valueAnimator
.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator va) {
// 执行进度
float rate = Float.parseFloat(va
.getAnimatedValue().toString()) / 500;
float y = viewY
+ (rate * (view.getHeight() - viewY));
view.setY(y);
}
});
}
break;
default:
break;
}
return true;
}
}
<FrameLayout 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" >
<View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#DD8500" />
<View
android:id="@+id/view_top"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#705856" />
</FrameLayout>