利用动画原理改变view位置

方案一、采用属性动画ValueAnimator

<!-- res/animator/value_animator.xml -->
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:valueFrom="100"
    android:valueTo="20"
    android:valueType="intType" />
 // 获取屏幕宽度
    final int maxWidth = getWindowManager().getDefaultDisplay().getWidth();
    ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.value_animator);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animator) {
            // 当前动画值,即为当前宽度比例值
            int currentValue = (Integer) animator.getAnimatedValue();
            // 根据比例更改目标view的宽度
            view.getLayoutParams().width = maxWidth * currentValue / 100;
            view.requestLayout();
        }
    });
    valueAnimator.start();

方案二、利用Interpolator.getInterpolation计算已经走过的距离

//利用Interpolator.getInterpolation计算已经走过的距离

package com.qianwang.qianbao.im.ui.main;

import java.util.ArrayList;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.qianwang.qianbao.im.R;
import com.qianwang.qianbao.im.ui.action.InitViews;
import com.qianwang.qianbao.im.views.pulltorefresh.internal.ViewCompat;


/**
 * 主界面tab view
 * 
 * @author zhangxiaolong
 * @since qianbao3.0
 */
public class MainTabView extends LinearLayout implements InitViews, OnGlobalLayoutListener
{
	private MainTabActivity mMainTabActivity;
	private LinearLayout mTabLayout;
	private TextView mTxtCursor;

	private int mCursorMoveSpace = 0;
	private float mCursorFromXDelta = 0;
	private ArrayList<BaseTabFragment> mFragments = null;
	
	private int tabCount = 4;
	private OnTabClickListener mOntaClickListener = new OnTabClickListener();
	
	public MainTabView(Context context) {
		super(context);
		initViews(context, null);
		bindListener();
	}
	
	public MainTabView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initViews(context, null);
		bindListener();
	}

	@Override
	public void initViews(Context context, View root)
	{
		setOrientation(LinearLayout.HORIZONTAL);
		LayoutInflater layoutInflater = LayoutInflater.from(context);
	    layoutInflater.inflate(getLayoutId(), this);
		
	    mTxtCursor = (TextView) findViewById(R.id.cursor);
		mTabLayout = (LinearLayout)findViewById(R.id.tab_layout);
		
		postDelayed(mDismissRunnable, 3000);
	}
	
    @Override
    public void bindListener()
    {
    	getViewTreeObserver().addOnGlobalLayoutListener(this);  
    }

	@Override
	public void initData()
	{

	}
	
	@Override
	public int getLayoutId()
	{
		return R.layout.main_top_tab;
	}
	
	@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
	@Override
    public synchronized void onGlobalLayout()
    {
		final int width = getWidth();
		if(width != 0)
		{
			int tabWidth = width / tabCount;
			mCursorMoveSpace = tabWidth;
			LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)mTxtCursor.getLayoutParams();
			params.width = tabWidth;
			mTxtCursor.setLayoutParams(params);
			
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
			{
				getViewTreeObserver().removeOnGlobalLayoutListener(this);
			}
			else
			{
				getViewTreeObserver().removeGlobalOnLayoutListener(this);
			}
		}
    }
	
	public void setTabCount(int tabCount)
	{
		this.tabCount = tabCount;
		
		setCursorLayout(0);
	}
	
	public void setCursorFromXDelta(int position)
	{
		mCursorFromXDelta = position * mCursorMoveSpace;
	}
	
	public int getCursorMoveSpace()
	{
		return mCursorMoveSpace;
	}
	
	/**
     * 设置cursor左边距
     * 
     * @param leftMargin cursor 距离左边的距离
     */
    public void setCursorLayout(int leftMargin)
    {
    	mTxtCursor.clearAnimation();
    	
    	LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)mTxtCursor.getLayoutParams();
		params.setMargins(leftMargin, 0, 0, 0);
		mTxtCursor.setLayoutParams(params);
		
		mCursorFromXDelta = leftMargin;
    }
    
    public void setMainTabActivity(MainTabActivity mainTabActivity)
    {
    	mMainTabActivity = mainTabActivity;
    }
    
    public void setSelectedTab(int index)
	{
        for (int i = 0; i < tabCount; i++)
		{
        	final View view = mTabLayout.getChildAt(i);
    		final TextView textView = (TextView) view.findViewById(R.id.main_tab_item_text); 
    		final int tag = (Integer)view.getTag() ;
    		textView.setSelected(tag == index);
		}
	}
    
	public View createTabItemView(String title, int icon, int index)
	{
		final View view = LayoutInflater.from(getContext()).inflate(R.layout.main_tab_item_view, null);
	
		final TextView textView = (TextView) view.findViewById(R.id.main_tab_item_text);          
//        textView.setText(title);  
		textView.setBackgroundResource(icon);
        view.setOnClickListener(mOntaClickListener);
        view.setTag(index);
		
		LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT);
		params.weight = 1.0f;
		mTabLayout.addView(view, params);
	
		return view;
	}
	
	/**
	 * 设置tab右上角消息指示可见性
	 * 
	 * @param cls tab位置上的fragment类名
	 * @param visibility
	 */
	public void setTabMsgIndicatorVisibility(int index, String fragmentName, int visibility, int count)
	{
		final View view = mTabLayout.getChildAt(index);
		final TextView indicator = (TextView) view.findViewById(R.id.main_tab_item_msg_indicator);
		
		if(indicator.getVisibility() != visibility)
			indicator.setVisibility(visibility);
		
		if(count > 0)
		{
			if(count > 99) 
			{
				indicator.setText("99+");
			}
			else
			{
				indicator.setText(Integer.toString(count));
			}
			indicator.setTag(count);
			indicator.setBackgroundResource(R.drawable.unread_indicator_yellow_bg);
		}
		else if(View.VISIBLE == visibility)
		{
			Object tag = indicator.getTag();
			int tagCount = 0;
			if(tag instanceof Integer)
			{
				tagCount = (Integer)tag;
			}
			
			if(tagCount == 0)
			{
				indicator.setText("");
				indicator.setBackgroundResource(R.drawable.unread_indicator_yellow_bg_small);
			}
		}
		else
		{
			indicator.setTag(0);
			indicator.setText("");
			indicator.setBackgroundResource(R.drawable.unread_indicator_yellow_bg_small);
		}
	}
	
	public class OnTabClickListener implements View.OnClickListener
	{
		@Override
		public void onClick(View v)
		{
			int index = (Integer)v.getTag();
			float toXDelta = index * mCursorMoveSpace;

			MarginLayoutParams params = (MarginLayoutParams) mTxtCursor.getLayoutParams();
			Animation animation = new TranslateAnimation(-params.leftMargin + mCursorFromXDelta, -params.leftMargin
					+ toXDelta, 0, 0);
			animation.setFillAfter(true);
			animation.setInterpolator(AnimationUtils.loadInterpolator(mMainTabActivity,
					android.R.anim.linear_interpolator));
			animation.setDuration(150);
			mTxtCursor.startAnimation(animation);

			if(index == mMainTabActivity.getViewPager().getCurrentItem())
			{
				BaseTabFragment fragment = mFragments.get(index);
				fragment.onTabClick();
			}
			else
			{
				mMainTabActivity.setCurrentItem(index);
			}
		}
	};
	
	public void startShow()
	{
		if(mSmoothScrollRunnable != null)
		{
			mSmoothScrollRunnable.stop();
		}
		
		int fromY = mMainTabActivity.getRootView().getPaddingTop();
		int toY = 0;
		if(fromY == toY) return;
		
		mSmoothScrollRunnable = new SmoothScrollRunnable(fromY, toY, 200);
		post(mSmoothScrollRunnable);
	}
	
	public void startDismiss()
	{
		if(mSmoothScrollRunnable != null)
		{
			mSmoothScrollRunnable.stop();
		}
		
		int fromY = mMainTabActivity.getRootView().getPaddingTop();
		int toY = -mTabLayout.getHeight();
		if(fromY == toY) return;
		
		mSmoothScrollRunnable = new SmoothScrollRunnable(fromY, toY, 500);
		post(mSmoothScrollRunnable);
	}
	
	private SmoothScrollRunnable mSmoothScrollRunnable = null;
	private Runnable mDismissRunnable = new Runnable()
	{
		@Override
		public void run()
		{
			startDismiss();
		}
	};
	
	final class SmoothScrollRunnable implements Runnable
	{
		private final Interpolator mInterpolator;
		private final int mScrollToY;
		private final int mScrollFromY;
		private final long mDuration;

		private boolean mContinueRunning = true;
		private long mStartTime = -1;
		private int mCurrentY = -1;

		public SmoothScrollRunnable(int fromY, int toY, long duration)
		{
			mContinueRunning = true;
			mScrollFromY = fromY;
			mScrollToY = toY;
			mInterpolator = new AccelerateInterpolator();
			mDuration = duration;
		}

		@Override
		public void run()
		{
			if (mStartTime == -1)
			{
				mStartTime = System.currentTimeMillis();
			}
			else
			{
				long normalizedTime = (1000 * (System.currentTimeMillis() - mStartTime)) / mDuration;
				normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0);

				final int deltaY = Math.round((mScrollFromY - mScrollToY)
						* mInterpolator.getInterpolation(normalizedTime / 1000f));
				mCurrentY = mScrollFromY - deltaY;
				setTabScroll(mCurrentY);
			}

			// If we're not at the target Y, keep going...
			if (mContinueRunning && mScrollToY != mCurrentY)
			{
				ViewCompat.postOnAnimation(MainTabView.this, this);
			}
			else
			{
				//stop...
			}
		}

		public void stop()
		{
			mContinueRunning = false;
			removeCallbacks(this);
		}
		
		private void setTabScroll(int value)
		{
			mMainTabActivity.getRootView().setPadding(0, value, 0, 0);
		}
	}
}

方案三、重写Animation.applyTransformation方法,在该方法中改变位置.参考SwipeRefreshLayout .java

//重写Animation.applyTransformation方法,在该方法中改变位置.参考SwipeRefreshLayout .java
package com.qianwang.qianbao.im.ui.friendscircle;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.Transformation;
import android.widget.FrameLayout;
import android.widget.ImageView;

public class FriendsCircleLoadingImage extends ImageView
{
	private static final Interpolator ANIMATION_INTERPOLATOR = new LinearInterpolator();
	private static final int ROTATION_ANIMATION_DURATION = 1200;
	private static final int RETURN_TO_ORIGINAL_POSITION_TIMEOUT = 1000;
	private static final float ACCELERATE_INTERPOLATION_FACTOR = 1.5f;
	
	private final Animation mRotateAnimation;
	private final Animation mAnimateToStartPosition;
	private final Matrix mHeaderImageMatrix;
	private final AccelerateInterpolator mAccelerateInterpolator;

	private float mRotationPivotX, mRotationPivotY;
	
	private final AnimationListener mReturnToStartPositionListener = new AnimationListener() {
        @Override
        public void onAnimationEnd(Animation animation) {
        	clearAnimation();
        	FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)getLayoutParams();
            lp.topMargin = 0;
			setLayoutParams(lp);
        }

		@Override
		public void onAnimationStart(Animation animation)
		{
		}

		@Override
		public void onAnimationRepeat(Animation animation)
		{
		}
    };
	
	public FriendsCircleLoadingImage(Context context)
	{
		this(context, null);
	}
	
	public FriendsCircleLoadingImage(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		
		setScaleType(ScaleType.MATRIX);
		mHeaderImageMatrix = new Matrix();
		setImageMatrix(mHeaderImageMatrix);

		mRotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		mRotateAnimation.setInterpolator(ANIMATION_INTERPOLATOR);
		mRotateAnimation.setDuration(ROTATION_ANIMATION_DURATION);
		mRotateAnimation.setRepeatCount(Animation.INFINITE);
		mRotateAnimation.setRepeatMode(Animation.RESTART);
		
		mAnimateToStartPosition = new Animation() {
	        @Override
	        public void applyTransformation(float interpolatedTime, Transformation t) {
	            int targetTop = 0;
	            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)getLayoutParams();
	            if (lp.topMargin != 0) {
	                targetTop = (lp.topMargin + (int)((0 - lp.topMargin) * interpolatedTime));
	            }
	            
	            lp.topMargin = targetTop;
				setLayoutParams(lp);
	        }
	    };
	    
	    mAccelerateInterpolator = new AccelerateInterpolator(ACCELERATE_INTERPOLATION_FACTOR);
	}
	
	public final void setLoadingDrawable(Drawable imageDrawable) {
		setImageDrawable(imageDrawable);

		if (null != imageDrawable) {
			mRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f);
			mRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f);
		}
	}
	
	protected void updateState(float percent, float dy) {
		float angle = percent * 360f;

		mHeaderImageMatrix.setRotate(angle, mRotationPivotX, mRotationPivotY);
//		mHeaderImageMatrix.postTranslate(0, dy);
		setImageMatrix(mHeaderImageMatrix);
		
		FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)getLayoutParams();
		if(lp.topMargin != (int)dy)
		{
			lp.topMargin = (int)dy;
			setLayoutParams(lp);
		}
	}

	protected void startLoading() {
		startAnimation(mRotateAnimation);
	}

	protected void stopLoading() {
		clearAnimation();
		if (null != mHeaderImageMatrix) {
			mHeaderImageMatrix.reset();
			setImageMatrix(mHeaderImageMatrix);
		}
		animateOffsetToStartPosition();
	}
	
	protected void animateOffsetToStartPosition() {
        mAnimateToStartPosition.reset();
        mAnimateToStartPosition.setDuration(RETURN_TO_ORIGINAL_POSITION_TIMEOUT);
        mAnimateToStartPosition.setAnimationListener(mReturnToStartPositionListener);
        mAnimateToStartPosition.setInterpolator(mAccelerateInterpolator);
        startAnimation(mAnimateToStartPosition);
    }

	
}


转载于:https://my.oschina.net/bruces/blog/540657

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值