android nineoldandroids

http://www.2cto.com/kf/201401/270169.html

下面是网上滑动删除的例子。

package com.example.swipedismisslistview;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;

import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.view.ViewHelper;
import com.nineoldandroids.view.ViewPropertyAnimator;


public class SwipeDismissListView extends ListView {
	/**
	 * 认为是用户滑动的最小距离
	 */
	private int mSlop;
	/**
	 * 滑动的最小速度
	 */
	private int mMinFlingVelocity;
	/**
	 * 滑动的最大速度
	 */
	private int mMaxFlingVelocity;
	/**
	 * 执行动画的时间
	 */
	protected long mAnimationTime = 150;
	/**
	 * 用来标记用户是否正在滑动中
	 */
	private boolean mSwiping;
	/**
	 * 滑动速度检测类
	 */
	private VelocityTracker mVelocityTracker;
	/**
	 * 手指按下的position
	 */
	private int mDownPosition;
	/**
	 * 按下的item对应的View
	 */
	private View mDownView;
	private float mDownX;
	private float mDownY;
	/**
	 * item的宽度
	 */
	private int mViewWidth;
	/**
	 * 当ListView的Item滑出界面回调的接口
	 */
	private OnDismissCallback onDismissCallback;

	/**
	 * 设置动画时间
	 * 
	 * @param mAnimationTime
	 */
	public void setmAnimationTime(long mAnimationTime) {
		this.mAnimationTime = mAnimationTime;
	}

	/**
	 * 设置删除回调接口
	 * 
	 * @param onDismissCallback
	 */
	public void setOnDismissCallback(OnDismissCallback onDismissCallback) {
		this.onDismissCallback = onDismissCallback;
	}

	public SwipeDismissListView(Context context) {
		this(context, null);
	}

	public SwipeDismissListView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public SwipeDismissListView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);

		ViewConfiguration vc = ViewConfiguration.get(context);
		mSlop = vc.getScaledTouchSlop();
		mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 8; // 获取滑动的最小速度
		mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); // 获取滑动的最大速度
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			handleActionDown(ev);
			break;
		case MotionEvent.ACTION_MOVE:
			return handleActionMove(ev);
		case MotionEvent.ACTION_UP:
			handleActionUp(ev);
			break;
		case MotionEvent.ACTION_CANCEL:
			//什么时候会触发这个事件
			//http://blog.csdn.net/ldwtill/article/details/10162819
			//Log.i("zhouke", "cancel......action");
			break;
		}
		return super.onTouchEvent(ev);
	}

	/**
	 * 按下事件处理
	 * 
	 * @param ev
	 * @return
	 */
	private void handleActionDown(MotionEvent ev) {
		mDownX = ev.getX();
		mDownY = ev.getY();

		mDownPosition = pointToPosition((int) mDownX, (int) mDownY);

		if (mDownPosition == AdapterView.INVALID_POSITION) {
			return;
		}

		mDownView = getChildAt(mDownPosition - getFirstVisiblePosition());

		if (mDownView != null) {
			mViewWidth = mDownView.getWidth();
		}

		// 加入速度检测
		mVelocityTracker = VelocityTracker.obtain();
		mVelocityTracker.addMovement(ev);
	}

	/**
	 * 处理手指滑动的方法
	 * 
	 * @param ev
	 * @return
	 */
	private boolean handleActionMove(MotionEvent ev) {
		if (mVelocityTracker == null || mDownView == null) {
			return super.onTouchEvent(ev);
		}

		float deltaX = ev.getX() - mDownX;
		float deltaY = ev.getY() - mDownY;

		// X方向滑动的距离大于mSlop并且Y方向滑动的距离小于mSlop,表示可以滑动
		if (Math.abs(deltaX) > mSlop && Math.abs(deltaY) < mSlop) {
			mSwiping = true;

			// 当手指滑动item,取消item的点击事件,不然我们滑动Item也伴随着item点击事件的发生
			MotionEvent cancelEvent = MotionEvent.obtain(ev);
			//int a=ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
			cancelEvent
					.setAction(MotionEvent.ACTION_CANCEL
							| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
			onTouchEvent(cancelEvent);
		}

		if (mSwiping) {
			// 跟谁手指移动item
			ViewHelper.setTranslationX(mDownView, deltaX);
			// 透明度渐变
			ViewHelper.setAlpha(
					mDownView,
					Math.max(0f,Math.min(1f, 1f - 2f * Math.abs(deltaX)/ mViewWidth)));

			// 手指滑动的时候,返回true,表示SwipeDismissListView自己处理onTouchEvent,其他的就交给父类来处理
			return true;
		}

		return super.onTouchEvent(ev);

	}

	/**
	 * 手指抬起的事件处理
	 * 
	 * @param ev
	 */
	private void handleActionUp(MotionEvent ev) {
		if (mVelocityTracker == null || mDownView == null || !mSwiping) {
			return;
		}

		float deltaX = ev.getX() - mDownX;

		// 通过滑动的距离计算出X,Y方向的速度
		mVelocityTracker.computeCurrentVelocity(1000);
		float velocityX = Math.abs(mVelocityTracker.getXVelocity());
		float velocityY = Math.abs(mVelocityTracker.getYVelocity());

		boolean dismiss = false; // item是否要滑出屏幕
		boolean dismissRight = false;// 是否往右边删除

		// 当拖动item的距离大于item的一半,item滑出屏幕
		if (Math.abs(deltaX) > mViewWidth / 2) {
			dismiss = true;
			dismissRight = deltaX > 0;
            Log.i("zhouke", "if....");
			// 手指在屏幕滑动的速度在某个范围内,也使得item滑出屏幕
		} else if (mMinFlingVelocity <= velocityX
				&& velocityX <= mMaxFlingVelocity && velocityY < velocityX) {
			dismiss = true;
			dismissRight = mVelocityTracker.getXVelocity() > 0;
			Log.i("zhouke", "else.... ");
		}

		if (dismiss) {
			
			// AnimatorSet set = new AnimatorSet();
			// set.playTogether(ObjectAnimator.ofFloat(mDownView,
			// "translationX", dismissRight ? mViewWidth : -mViewWidth),
			// ObjectAnimator.ofFloat(mDownView, "alpha", 0));
			// set.setDuration(mAnimationTime).start();
			// set.addListener(new AnimatorListenerAdapter() {
			// @Override
			// public void onAnimationEnd(Animator animation) {
			// //Item滑出界面之后执行删除
			// performDismiss(mDownView, mDownPosition);
			// }
			// });
            
			ViewPropertyAnimator.animate(mDownView)
					.translationX(dismissRight ? mViewWidth : -mViewWidth)
					// X轴方向的移动距离
					.alpha(0).setDuration(mAnimationTime)
					.setListener(new AnimatorListenerAdapter() {
						@Override
						public void onAnimationEnd(Animator animation) {
							// Item滑出界面之后执行删除
							performDismiss(mDownView, mDownPosition);
						}
					});
		} else {
			// 将item滑动至开始位置
			ViewPropertyAnimator.animate(mDownView).translationX(0).alpha(1)
					.setDuration(mAnimationTime).setListener(null);
		}

		// 移除速度检测
		if (mVelocityTracker != null) {
			mVelocityTracker.recycle();
			mVelocityTracker = null;
		}

		mSwiping = false;
	}

	/**
	 * 在此方法中执行item删除之后,其他的item向上或者向下滚动的动画,并且将position回调到方法onDismiss()中
	 * 
	 * @param dismissView
	 * @param dismissPosition
	 */
	private void performDismiss(final View dismissView,
			final int dismissPosition) {
		final ViewGroup.LayoutParams lp = dismissView.getLayoutParams();// 获取item的布局参数
		final int originalHeight = dismissView.getHeight();// item的高度
      Log.i("zhouke", "originalHeight:"+originalHeight);
		ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 0)
				.setDuration(mAnimationTime);
		animator.start();
	
		animator.addListener(new AnimatorListenerAdapter() {
			@Override
			public void onAnimationEnd(Animator animation) {
				if (onDismissCallback != null) {
					onDismissCallback.onDismiss(dismissPosition);
				}
                Log.i("zhouke", "animation end");
				// 这段代码很重要,因为我们并没有将item从ListView中移除,而是将item的高度设置为0
				// 所以我们在动画执行完毕之后将item设置回来
				ViewHelper.setAlpha(dismissView, 1f);
				ViewHelper.setTranslationX(dismissView, 0);
				ViewGroup.LayoutParams lp = dismissView.getLayoutParams();
				lp.height = originalHeight;
				dismissView.setLayoutParams(lp);

			}
		});

		animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator valueAnimator) {
				
				// 这段代码的效果是ListView删除某item之后,其他的item向上滑动的效果
				lp.height = (Integer) valueAnimator.getAnimatedValue();
				Log.i("zhouke", "animation update"+lp.height);
				dismissView.setLayoutParams(lp);
			}
		});

	}

	/**
	 * 删除的回调接口
	 * 
	 * @author xiaanming
	 * 
	 */
	public interface OnDismissCallback {
		public void onDismiss(int dismissPosition);
	}

}
另一个简单需求,把button 的宽度增加到500.

package com.example.swipedismisslistview;

import com.nineoldandroids.animation.IntEvaluator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class Activity2 extends Activity implements OnClickListener {
	private Button btn1;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		setContentView(R.layout.layout2);
		btn1=(Button) findViewById(R.id.button1);
		btn1.setOnClickListener(this);
		super.onCreate(savedInstanceState);
	}
	private void performAnimate(final View target, final int start, final int end) {
	    ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
	 
	    valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
	 
	        //持有一个IntEvaluator对象,方便下面估值的时候使用
	        private IntEvaluator mEvaluator = new IntEvaluator();
	 
	        @Override
	        public void onAnimationUpdate(ValueAnimator animator) {
	            //获得当前动画的进度值,整型,1-100之间
	            int currentValue = (Integer)animator.getAnimatedValue();
	            //Log.i("zhouke", "current value:"+currentValue+":"+Thread.currentThread().getName());
	            //计算当前进度占整个动画过程的比例,浮点型,0-1之间
	            float fraction = currentValue / 100f; 
	 
	            //这里我偷懒了,不过有现成的干吗不用呢
	            //直接调用整型估值器通过比例计算出宽度,然后再设给Button
	           
	            Integer evaluate = mEvaluator.evaluate(fraction, start, end);
	            Log.i("zhouke", "fraction:"+fraction+"evaluate:"+evaluate);
	            target.getLayoutParams().width = evaluate;
	            target.requestLayout();
	        }
	    });
	 
	    valueAnimator.setDuration(5000).start();
	}

	 
	@Override
	public void onClick(View v) {
	    if (v == btn1) {
	        performAnimate(btn1, btn1.getWidth(), 500);
	    }
	}
}


文字增长:

mainactivity

package com.bear.risenumbertest;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

import com.bear.risenumbertest.lib.RiseNumberTextView;
import com.bear.risenumbertest.lib.RiseNumberTextView.EndListener;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 获取到RiseNumberTextView对象
		RiseNumberTextView rnTextView = (RiseNumberTextView) findViewById(R.id.risenumber_textview);
		// 设置数据
		rnTextView.withNumber(2666.50f);
		// 设置动画播放时间
		rnTextView.setDuration(5000);
		// 开始播放动画
		rnTextView.start();
		// 监听动画播放结束
		rnTextView.setOnEnd(new EndListener() {

			@Override
			public void onEndFinish() {
				Toast.makeText(MainActivity.this, "数据增长完毕...", Toast.LENGTH_SHORT).show();
			}
		});
	}
}

package com.bear.risenumbertest.lib;

public interface RiseNumberBase {
    public void start();
    public RiseNumberTextView withNumber(float number);
    public RiseNumberTextView withNumber(int number);
    public RiseNumberTextView setDuration(long duration);
    public void setOnEnd(RiseNumberTextView.EndListener callback);
}


package com.bear.risenumbertest.lib;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

import com.nineoldandroids.animation.ValueAnimator;

import java.text.DecimalFormat;

public class RiseNumberTextView extends TextView implements RiseNumberBase {

	private static final int STOPPED = 0;

	private static final int RUNNING = 1;

	private int mPlayingState = STOPPED;

	private float number;

	private float fromNumber;

	private long duration = 1500;
	/**
	 * 1.int 2.float
	 */
	private int numberType = 2;

	private DecimalFormat fnum;

	private EndListener mEndListener = null;

	final static int[] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE };

	public RiseNumberTextView(Context context) {
		super(context);
	}

	public RiseNumberTextView(Context context, AttributeSet attr) {
		super(context, attr);
	}

	public RiseNumberTextView(Context context, AttributeSet attr, int defStyle) {
		super(context, attr, defStyle);
	}

	public interface EndListener {
		public void onEndFinish();
	}

	public boolean isRunning() {
		return (mPlayingState == RUNNING);
	}

	private void runFloat() {
		ValueAnimator valueAnimator = ValueAnimator.ofFloat(fromNumber, number);
		valueAnimator.setDuration(duration);

		valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator valueAnimator) {

				setText(fnum.format(Float.parseFloat(valueAnimator.getAnimatedValue().toString())));
				if (valueAnimator.getAnimatedFraction() >= 1) {
					mPlayingState = STOPPED;
					if (mEndListener != null)
						mEndListener.onEndFinish();
				}
			}

		});
		valueAnimator.start();
	}

	private void runInt() {
		ValueAnimator valueAnimator = ValueAnimator.ofInt((int) fromNumber, (int) number);
		valueAnimator.setDuration(duration);

		valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator valueAnimator) {

				setText(valueAnimator.getAnimatedValue().toString());
				if (valueAnimator.getAnimatedFraction() >= 1) {
					mPlayingState = STOPPED;
					if (mEndListener != null)
						mEndListener.onEndFinish();
				}
			}
		});
		valueAnimator.start();
	}

	static int sizeOfInt(int x) {
		for (int i = 0;; i++)
			if (x <= sizeTable[i])
				return i + 1;
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		fnum = new DecimalFormat("##0.00");
	}

	@Override
	public void start() {

		if (!isRunning()) {
			mPlayingState = RUNNING;
			if (numberType == 1)
				runInt();
			else
				runFloat();
		}
	}

	@Override
	public RiseNumberTextView withNumber(float number) {

		this.number = number;
		numberType = 2;
		if (number > 1000) {
			Log.i("zhouke", "sizeofInt:"+(sizeOfInt((int)number)-2));
			fromNumber = number - (float) Math.pow(10, sizeOfInt((int) number) - 2);
			Log.i("zhouke", "1formaNumber:"+fromNumber+"number:"+number);
		} else {
			fromNumber = number / 2;
			Log.i("zhouke", "2formaNumber:"+fromNumber);
		}

		return this;
	}

	@Override
	public RiseNumberTextView withNumber(int number) {
		this.number = number;
		numberType = 1;
		if (number > 1000) {
			fromNumber = number - (float) Math.pow(10, sizeOfInt((int) number) - 2);
		} else {
			fromNumber = number / 2;
		}

		return this;

	}

	@Override
	public RiseNumberTextView setDuration(long duration) {
		this.duration = duration;
		return this;
	}

	@Override
	public void setOnEnd(EndListener callback) {
		mEndListener = callback;
	}

}


===========

 ViewHelper.setRotationX(view, baseRotation);
        ViewHelper.setTranslationY(view, fromY);

        ViewPropertyAnimator
                .animate(view)
                .setInterpolator(new AccelerateDecelerateInterpolator())
                .setDuration(duration)
                .setStartDelay(startDelay)
                .rotationX(0)
                .translationY(0)
                .start();







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值