padding式的上下拉反弹,下拉放大顶部图片,松开反弹,上拉显示空白区域,松开反弹.
和现在的淘宝客户端一样下拉时放大顶部图片,并自动回收,费话不多说,上代码:
package com.spider.reader.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import com.spider.reader.R;
/**
* 自定义上拉下拉反弹ScrollView
*
* @author Seal Created on 2014-1-10 上午9:15:26
* @note padding式的上下拉反弹,下拉放大顶部图片,松开反弹,上拉显示空白区域,松开反弹
*/
public class PullScrollView extends ScrollView {
private ViewGroup inner;
View childOne = null;
private Rect rect;
private float preY;// 之前的Y坐标的记录
private float nowY;// 现在的Y坐标的记录
private float moveY = 0;// 滑动距离
private boolean isUpRecord = false;// 下拉记录
private boolean isDownRecord = false;// 上拉记录
private ImageView image;
private Context context;
private Drawable d;
private String title;
private final float imageHight = 0;
public PullScrollView(Context context) {
super(context);
this.context = context;
}
public PullScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.PullScrollView, defStyle, 0);
d = a.getDrawable(R.styleable.PullScrollView_pic);
title = a.getString(R.styleable.PullScrollView_title);
a.recycle();
}
public PullScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.PullScrollView);
d = a.getDrawable(R.styleable.PullScrollView_pic);
title = a.getString(R.styleable.PullScrollView_title);
a.recycle();
}
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
inner = (ViewGroup) getChildAt(0);
if (inner.getChildCount() > 0) {
childOne = inner.getChildAt(0);
}
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, (int) imageHight);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
image = new ImageView(context);
image.setId(0x10000101);
if (d != null) {
image.setBackgroundDrawable(d);
}
inner.addView(image, params);
if (childOne != null) {
RelativeLayout.LayoutParams oneParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
oneParams.addRule(RelativeLayout.BELOW, image.getId());
childOne.setLayoutParams(oneParams);
}
rect = new Rect();
rect.set(inner.getPaddingLeft(), inner.getPaddingTop(),
inner.getPaddingRight(), inner.getPaddingBottom());
}
super.onFinishInflate();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
nowY = ev.getY();
record();
break;
case MotionEvent.ACTION_MOVE:
nowY = ev.getY();
record();
if (isUpRecord || isDownRecord) {
moveY = nowY - preY;
}
break;
case MotionEvent.ACTION_UP:
if (isUpRecord || isDownRecord) {
startRecorverAnimation();
}
break;
default:
break;
}
if (isUpRecord && moveY > 0) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
(int) (imageHight + moveY / 2));
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
image.setLayoutParams(params);
} else if (isDownRecord && moveY < 0) {
inner.setPadding(rect.left, rect.top, rect.right,
(int) (rect.bottom - moveY / 2));
}
return super.onTouchEvent(ev);
}
private void startRecorverAnimation() {
Animation transAnimation = null;
if (inner.getPaddingBottom() > rect.bottom) {
isDownRecord = false;
transAnimation = new TranslateAnimation(0, 0,
-inner.getPaddingBottom(), rect.bottom);
transAnimation.setDuration(200);
inner.setAnimation(transAnimation);
inner.startAnimation(transAnimation);
inner.setPadding(rect.left, rect.top, rect.right, rect.bottom);
} else if (image.getHeight() > imageHight) {
new AsyncTask<String, Float, String>() {
@Override
protected String doInBackground(String... params) {
while (image.getHeight() > imageHight) {
float distance = image.getHeight() - imageHight;
int step = 30;// 变化步伐
distance = distance > step ? distance - step : 0;
publishProgress(distance);
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Float... values) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
(int) (imageHight + values[0]));
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
image.setLayoutParams(params);
super.onProgressUpdate(values);
}
protected void onPostExecute(String result) {
isUpRecord = false;
};
}.execute("kaishi");
}
}
private void record() {
if (!isUpRecord && getScrollY() == 0) {
preY = nowY;
isUpRecord = true;
isDownRecord = false;
} else if (!isDownRecord
&& getScrollY() == inner.getMeasuredHeight() - getHeight()) {
preY = nowY;
isDownRecord = true;
isUpRecord = false;
}
}
}
<com.spider.reader.view.PullScrollView
xmlns:pullscroll="http://schemas.android.com/apk/res/com.spider.reader"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/head_layout"
android:fadingEdge="none"
pullscroll:pic="@drawable/icon"
pullscroll:title="testTitle" />
<declare-styleable name="PullScrollView">
<attr name="pic" format="reference" />
<attr name="title" format="string" />
</declare-styleable>