最近在研究path的首页滑动效果,发现啪啪也已经实现了这个效果,自己网上找了代码,又自己试试,发现如果是用两个ImageView 做的话,可以实现,但是用listView的话,滑动就会出问题,现在把代码粘贴如下,望各位指点迷津:
主界面的xml:
<com.example.testpathscroll.MyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="@+id/iv1"
android:layout_width="fill_parent"
android:layout_height="200dip"
android:scaleType="center"
android:src="@drawable/bg" />
<ImageView
android:id="@+id/iv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/abcd" />
</LinearLayout>
<RelativeLayout
android:id="@+id/clock_rl"
android:layout_width="wrap_content"
android:layout_height="158dp" >
<include
android:id="@+id/clock"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_marginTop="40dp"
layout="@layout/clock" />
</RelativeLayout>
</FrameLayout>
</com.example.testpathscroll.MyScrollView>
其中主要代码就是第一个Linear中的两个ImageView;
自定义的MyScrollView:
public class MyScrollView extends ScrollView {
public static interface OnPositionChangedListener {
public void onPositionChanged(int position);
public void onScollPositionChanged(View scrollBarPanel, int top);
}
private OnPositionChangedListener mPositionChangedListener;
static int k = 50;
ImageView iv1;
ImageView iv2;
int left, top;
// 记录初始的位置
int m_top;
float startX, startY;
float currentX, currentY;
int rootW, rootH;
private boolean isCount = false;// 是否开始计算
int iv1H;
int iv2H;
// 记录下面布局的上高度,就是上面图片的下边
int t;
Scroller scroller;
int myHeight, myHeight2;
int myWidth, myWidth2;
// View mClock;
Context mContext;
// 时间
// PopupWindow mPopUp;
// 判断显示还是隐藏
boolean flag = false;
ScrollView mScrollView;
RelativeLayout mRelativel;
int temp;
TranslateAnimation ta=null;
//尝试使用Scroller
Scroller mScroller;
/*sdfsdfsdf*/
private View inner1,inner2;// 孩子
private float y;// 坐标
private Rect normal2 = new Rect();// 矩形空白
private Rect normal1 = new Rect();// 矩形空白
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
// 第一张图片的高度,这个是需要(可以按照比例来制定,或者使用固定值,按照需要来)
Bitmap bm = BitmapCache.getInstance().getBitmap(R.drawable.bg, context);
myHeight = bm.getHeight();
myWidth = bm.getWidth();
// 第二张图片
Bitmap bm2 = BitmapCache.getInstance().getBitmap(R.drawable.abcd,
context);
myHeight2 = bm2.getHeight();
myWidth2 = bm2.getWidth();
temp=(int) (200*context.getResources().getDisplayMetrics().density);
//
mScroller=new Scroller(context);
//setFocusable(true);
// setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
// setWillNotDraw(false);
}
public void setOnPositionChangedListener(
OnPositionChangedListener onPositionChangedListener) {
mPositionChangedListener = onPositionChangedListener;
}
// public void openTimeShow() {
// // set position
// mPopUp.showAtLocation(findViewById(R.id.ll), Gravity.CENTER, 0, 0);
// // mPopUp.showAsDropDown(view, 0, 0);
// }
// public void closeTimeShow(){
// mPopUp.dismiss();
// }
/**
* 所有子View被加载后触发
* */
protected void onFinishInflate() {
super.onFinishInflate();
iv1 = (ImageView) findViewById(R.id.iv1);
iv2 = (ImageView) findViewById(R.id.iv);
// mClock=(View) findViewById(R.id.clock);
mScrollView = (ScrollView) findViewById(R.id.ll);
setLongClickable(true);
scroller = new Scroller(getContext(),
new AccelerateDecelerateInterpolator());
// View view=LayoutInflater.from(mContext).inflate(R.id.clock_rl, null);
// mPopUp=new PopupWindow(view, LayoutParams.WRAP_CONTENT,
// LayoutParams.WRAP_CONTENT);
// mPopUp.setFocusable(false);
// mPopUp.setOutsideTouchable(true);
mRelativel = (RelativeLayout) findViewById(R.id.clock_rl);
/*sdfsdf*/
inner1 = iv1;
inner2 = iv2;// 获取其孩子
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
m_top = iv2.getTop();
// 两张图片(两个布局的高度)
iv1H = iv1.getHeight();
iv2H = iv2.getHeight();
Log.i("TAG", iv1H + "---" + iv2H + "---" + m_top);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
currentX = event.getX();
currentY = event.getY();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
if(ta!=null){
ta.cancel();
ta=null;
}
left = iv2.getLeft();
top = iv2.getTop();
rootW = getWidth();
rootH = getHeight();
// Log.i("TAG", "iv1H高度ACTION_DOWN---"+iv1H);
currentX = event.getX();
currentY = event.getY();
startX = currentX;
startY = currentY;
//Rect2
if (normal2.isEmpty()) {
// 填充矩形,目的:就是告诉this:我现在已经有了,你松开的时候记得要执行回归动画.
normal2.set(inner2.getLeft(), inner2.getTop(),
inner2.getRight(), inner2.getBottom());
}
//Rect1
if (normal1.isEmpty()) {
// 填充矩形,目的:就是告诉this:我现在已经有了,你松开的时候记得要执行回归动画.
normal1.set(inner1.getLeft(), inner1.getTop(),
inner1.getRight(), inner1.getBottom());
}
mPositionChangedListener.onScollPositionChanged(this,
getHeight() / 2);
break;
}
case MotionEvent.ACTION_MOVE:
Log.i("TAG", iv2.getY()+"!!!!!!!!!!!!!!!!!!");
int c_current = (int) currentY;
int l = (int) (left + currentX - startX);
int deltaY=(int) (currentY - startY);
if (!isCount) {
deltaY = 0; // 在这里要归0.
}
// 获取滑动距离
t = (int) (top + deltaY);
// Log.i("TAG", (currentY -
// startY)+"-----currentY - startY----!!!!"+currentY+"!!!!"+startY);
if (deltaY >= 0) {// 向下滑动
if (t > myHeight) {
t = myHeight;
}
// 控制时间条的位置
if (c_current > 854) {
c_current = 854;
}
} else {// 向上滑动
// 854 IS A TEST PX,the Height of screen
if (myHeight2 >= 854) {
if ((myHeight2 - 854) < -t) {
t = 854 - myHeight2;
}
} else {
if (myHeight2 - t < 800) {
t = 854 - myHeight2;
}
}
// 控制位置(800是屏幕的高度)
if (c_current < 0) {
c_current = 0;
}
}
mPositionChangedListener.onPositionChanged((int) currentY);
mPositionChangedListener.onScollPositionChanged(this,
(int) (startY - currentY));
//iv2.layout(left, t, left + iv2.getWidth(), t + iv2.getHeight());
inner2.layout(left, t, left + iv2.getWidth(), t + iv2.getHeight());
inner1.layout(0, 0, iv1.getWidth(), t);
isCount = true;
break;
case MotionEvent.ACTION_UP:
// closeTimeShow();
if (t <= temp) {// m_top
} else {
//System.out.println(temp+"------------"+t);
//animation(iv2, 0, 0, 0, temp - t);
//animation(iv1, 0, 0, 0, -temp/2);
if (isNeedAnimation()) {
animation();
isCount = false;
}
// 更新结束后,使用动画控制偏移过程, 3s内到位
// //mScroller.startScroll(0, 0, 0, temp,3000);
// // 重绘控件
// invalidate();
// iv2.layout(left, temp, left + iv2.getWidth(), temp + iv2.getHeight());
//iv1.layout(0, 0, iv1.getWidth(), temp);
}
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
}
return true;
}
/***
* 是否需要开启动画
*
* 如果矩形不为空,返回true,否则返回false.
*
*
* @return
*/
public boolean isNeedAnimation() {
return !normal2.isEmpty()&&!normal1.isEmpty();
}
/***
* 开启动画移动
*/
public void animation() {
// 开启移动动画
System.out.println(inner2.getTop()+"----inner2.getTop()----"+normal2.top+"---normal.top-----");
TranslateAnimation ta = new TranslateAnimation(0, 0, inner2.getTop()-normal2.top,
0);
ta.setDuration(300);
// TranslateAnimation ta1=new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 1f, Animation.RELATIVE_TO_PARENT, 1f, Animation.RELATIVE_TO_PARENT, 1f, Animation.RELATIVE_TO_PARENT, 0.5f);
// ta1.setDuration(500);
// ScaleAnimation sa=new ScaleAnimation(1.0f, 1.0f, 1.5f, 1.0f,
// Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f);
// sa.setDuration(300);
MyAnimation ma=new MyAnimation();
inner2.startAnimation(ta);
inner1.startAnimation(ma);
// 设置回到正常的布局位置
inner2.layout(normal2.left, normal2.top, normal2.right, normal2.bottom);
inner1.layout(normal1.left, normal1.top, normal1.right, normal1.bottom);
// 清空矩形
normal1.setEmpty();
normal2.setEmpty();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) { // 如果返回true,表示动画还没有结束
// 产生平滑的动画效果,根据当前偏移量,每次滚动一点
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
// 此时同样也需要刷新View ,否则效果可能有误差
postInvalidate();
} else { //如果返回false,表示startScroll完成
}
}
public void animation(View view, float fromx, float tox, float fromY,
float toy) {
// 开启移动动画
ta = new TranslateAnimation(0, 0, fromY, toy);
ta.setInterpolator(new AccelerateDecelerateInterpolator());
ta.setDuration(500);
ta.setFillAfter(true);
//if(view.getId()==iv2.getId()){
ta.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
//返回初始位置
iv2.layout(left, temp, left + iv2.getWidth(), temp + iv2.getHeight());
iv1.layout(0, 0, iv1.getWidth(), temp);
//view.clearAnimation();
//postInvalidate();
//Log.i("TAG", "iv1.getY() + iv2.getY()"+iv1.getY()+"----" + iv2.getY()+"---"+temp);
}
});
//}
view.startAnimation(ta);
// 设置回到正常的布局位置
}
}
这段代码就是处理下拉,反弹效果的。
主界面java文件:
public class MainActivity extends Activity implements OnPositionChangedListener{// implements OnTouchListener, OnPositionChangedListener
MyScrollView ll;
FrameLayout clockLayout;
private ExtendedListView dataListView;
private boolean areButtonsShowing;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll = (MyScrollView) findViewById(R.id.ll);
clockLayout = (FrameLayout)findViewById(R.id.clock);
ll.setOnPositionChangedListener(this);
}
private float[] computMinAndHour(int currentMinute, int currentHour) {
float minuteRadian = 6f * currentMinute;
float hourRadian = 360f / 12f * currentHour;
float[] rtn = new float[2];
rtn[0] = minuteRadian;
rtn[1] = hourRadian;
return rtn;
}
private float[] lastTime = {
0f, 0f
};
private RotateAnimation[] computeAni(int min, int hour) {
RotateAnimation[] rtnAni = new RotateAnimation[2];
float[] timef = computMinAndHour(min, hour);
// AnimationSet as = new AnimationSet(true);
// 创建RotateAnimation对象
// 0--图片从哪开始旋转
// 360--图片旋转多少度
// Animation.RELATIVE_TO_PARENT, 0f,// 定义图片旋转X轴的类型和坐标
// Animation.RELATIVE_TO_PARENT, 0f);// 定义图片旋转Y轴的类型和坐标
RotateAnimation ra = new RotateAnimation(lastTime[0], timef[0], Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
ra.setFillAfter(true);
ra.setFillBefore(true);
// 设置动画的执行时间
ra.setDuration(800);
// 将RotateAnimation对象添加到AnimationSet
// as.addAnimation(ra);
// 将动画使用到ImageView
rtnAni[0] = ra;
lastTime[0] = timef[0];
// AnimationSet as2 = new AnimationSet(true);
// 创建RotateAnimation对象
// 0--图片从哪开始旋转
// 360--图片旋转多少度
// Animation.RELATIVE_TO_PARENT, 0f,// 定义图片旋转X轴的类型和坐标
// Animation.RELATIVE_TO_PARENT, 0f);// 定义图片旋转Y轴的类型和坐标
RotateAnimation ra2 = new RotateAnimation(lastTime[1], timef[1], Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
// 设置动画的执行时间
ra2.setFillAfter(true);
ra2.setFillBefore(true);
ra2.setDuration(800);
// 将RotateAnimation对象添加到AnimationSet
// as2.addAnimation(ra2);
// 将动画使用到ImageView
rtnAni[1] = ra2;
lastTime[1] = timef[1];
return rtnAni;
}
@Override
public void onPositionChanged(int position) {
TextView datestr = ((TextView) findViewById(R.id.clock_digital_date));
datestr.setText("上午");
int hour = Calendar.getInstance().getTime().getHours()+position;
String tmpstr = "";
if (hour > 12) {
hour = hour - 12;
datestr.setText("下午");
tmpstr += " ";
} else if (0 < hour && hour < 10) {
tmpstr += " ";
}
tmpstr += hour + ":" + Calendar.getInstance().getTime().getMinutes();
((TextView) findViewById(R.id.clock_digital_time)).setText(tmpstr);
RotateAnimation[] tmp = computeAni(Calendar.getInstance().getTime().getMinutes(),hour);
ImageView minView = (ImageView) findViewById(R.id.clock_face_minute);
minView.startAnimation(tmp[0]);
ImageView hourView = (ImageView) findViewById(R.id.clock_face_hour);
hourView.setImageResource(R.drawable.clock_hour_rotatable);
hourView.startAnimation(tmp[1]);
}
@Override
public void onScollPositionChanged(View scrollBarPanel, int top) {
MarginLayoutParams layoutParams = (MarginLayoutParams)clockLayout.getLayoutParams();
layoutParams.setMargins(0, top, 0, 0);
clockLayout.setLayoutParams(layoutParams);
}
}
上面的效果经过测试还可以达到要求。但是实际项目中用到的可能是listview,而不是ImageView,这就会产生点击事件传递的问题。
希望有经验的大侠给点指点~小弟不胜感激!