使用ViewFilter设置动画瓷片

anim

slide_bottom_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="3000"
        android:fromYDelta="0.0"
        android:toYDelta="100.0%p" />

</set>

slide_top_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="3000"
        android:fromYDelta="-100.0%p"
        android:toYDelta="0.0" />

</set>

slide_left_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="3000"
        android:fromXDelta="-100.0%p"
        android:toXDelta="0.0" />

</set>

slide_left_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="3000"
        android:fromXDelta="0.0"
        android:toXDelta="-100.0%p" />

</set>

slide_right_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="3000"
        android:fromXDelta="100.0%p"
        android:toXDelta="0.0" />

</set>

slide_right_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="3000"
        android:fromXDelta="0.0"
        android:toXDelta="100.0%p" />

</set>


TileAnimator.java



import java.util.ArrayList;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ViewFlipper;

public class TileAnimator extends TileAnimatorLayout {
	private static final String TAG = "TileAnimator";
	private static final boolean LOGD = false;

	private static final int DEFAULT_INTERVAL = 5000;

	private int mFlipInterval = DEFAULT_INTERVAL;
	private boolean mAutoStart = false;

	private boolean mRunning = false;
	private boolean mStarted = false;
	private boolean mVisible = false;
	private boolean mUserPresent = true;
	private ArrayList<TilesFrameEntity> entities = new ArrayList<TilesFrameEntity>();

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

	public TileAnimator(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public ArrayList<TilesFrameEntity> getEntities() {
		return entities;
	}

	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			final String action = intent.getAction();
			if (Intent.ACTION_SCREEN_OFF.equals(action)) {
				mUserPresent = false;
				updateRunning();
			} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
				mUserPresent = true;
				updateRunning(false);
			}
		}
	};

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();

		final IntentFilter filter = new IntentFilter();
		filter.addAction(Intent.ACTION_SCREEN_OFF);
		filter.addAction(Intent.ACTION_USER_PRESENT);
		getContext().registerReceiver(mReceiver, filter);

		if (mAutoStart) {
			startFlipping();
		}
	}

	@Override
	protected void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		mVisible = false;

		getContext().unregisterReceiver(mReceiver);
		updateRunning();
	}

	@Override
	protected void onWindowVisibilityChanged(int visibility) {
		super.onWindowVisibilityChanged(visibility);
		mVisible = visibility == VISIBLE;
		updateRunning(false);
	}

	/**
	 * How long to wait before flipping to the next view
	 * 
	 * @param milliseconds
	 *            time in milliseconds
	 */
	public void setFlipInterval(int milliseconds) {
		mFlipInterval = milliseconds;
	}

	/**
	 * Start a timer to cycle through child views
	 */
	public void startFlipping() {
		mStarted = true;
		updateRunning();
	}

	/**
	 * No more flips
	 */
	public void stopFlipping() {
		mStarted = false;
		updateRunning();
	}

	@Override
	public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
		super.onInitializeAccessibilityEvent(event);
		event.setClassName(ViewFlipper.class.getName());
	}

	@Override
	public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
		super.onInitializeAccessibilityNodeInfo(info);
		info.setClassName(ViewFlipper.class.getName());
	}

	/**
	 * Internal method to start or stop dispatching flip {@link Message} based
	 * on {@link #mRunning} and {@link #mVisible} state.
	 */
	private void updateRunning() {
		updateRunning(true);
	}

	/**
	 * Internal method to start or stop dispatching flip {@link Message} based
	 * on {@link #mRunning} and {@link #mVisible} state.
	 * 
	 * @param flipNow
	 *            Determines whether or not to execute the animation now, in
	 *            addition to queuing future flips. If omitted, defaults to
	 *            true.
	 */
	private void updateRunning(boolean flipNow) {
		boolean running = mVisible && mStarted && mUserPresent;
		if (running != mRunning) {
			if (running) {
				showOnly(mWhichChild, flipNow);
				Message msg = mHandler.obtainMessage(FLIP_MSG);
				int interval = getInterval(mWhichChild);
				mHandler.sendMessageDelayed(msg, interval);
			} else {
				mHandler.removeMessages(FLIP_MSG);
			}
			mRunning = running;
		}
		if (LOGD) {
			Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted="
					+ mStarted + ", mUserPresent=" + mUserPresent
					+ ", mRunning=" + mRunning);
		}
	}

	@Override
	public void addView(View child) {
		super.addView(child);
	}

	private int parse2Int(String s) {
		int res = 5;
		try {
			res = Integer.parseInt(s);
			if (res < 5) {
				res = 5;
			}
			return res * 1000;
		} catch (Exception e) {
			Log.e(TAG, "parse2Int", e);
		}
		return mFlipInterval;
	}

	/**
	 * Returns true if the child views are flipping.
	 */
	public boolean isFlipping() {
		return mStarted;
	}

	/**
	 * 添加瓷片元素
	 * @param entities
	 * @param type
	 */
	public void setTilesFrame(ArrayList<TilesFrameEntity> entities, int type) {
		stopFlipping();
		this.entities = entities;
		this.removeAllViews();
		for (TilesFrameEntity e : entities) {
			ImageView img = new ImageView(getContext());
			if (e.mDrawable != null) {
				img.setBackgroundDrawable(e.mDrawable);
			}
			img.setScaleType(ScaleType.FIT_XY);
			this.addView(img, new FrameLayout.LayoutParams(
					FrameLayout.LayoutParams.FILL_PARENT,
					FrameLayout.LayoutParams.FILL_PARENT));
		}
		mAutoStart = true;
		startFlipping();
	}

	/**
	 * 获取间隔时间
	 * @param next
	 * @return
	 */
	private int getInterval(int next) {
		if (next >= getChildCount()) {
			next = 0;
		} else if (next < 0) {
			next = getChildCount() - 1;
		}
		if (entities != null && !entities.isEmpty() && next >= 0
				&& next < entities.size()) {
			return parse2Int(entities.get(next).getDuration());
		}
		return mFlipInterval;
	}

	/**
	 * Returns true if this view automatically calls {@link #startFlipping()}
	 * when it becomes attached to a window.
	 */
	public boolean isAutoStart() {
		return mAutoStart;
	}

	private final int FLIP_MSG = 1;

	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			if (msg.what == FLIP_MSG) {
				if (mRunning) {
					showNext();
					msg = obtainMessage(FLIP_MSG);
					int interval = getInterval(mWhichChild + 1);
					sendMessageDelayed(msg, interval);
				}
			}
		}
	};
}

TileAnimatorLayout.java

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.ViewAnimator;

public class TileAnimatorLayout extends FrameLayout {

	public TileAnimatorLayout(Context context) {
		super(context);
		initViewAnimator(context, null);
	}

	public TileAnimatorLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		initViewAnimator(context, attrs);
	}

	int mWhichChild = 0;
	boolean mFirstTime = true;

	boolean mAnimateFirstTime = true;

	Animation mInAnimation;
	Animation mOutAnimation;
	boolean mMeasureAllChildren = true;

	/**
	 * Initialize this {@link ViewAnimator}, possibly setting
	 * {@link #setMeasureAllChildren(boolean)} based on {@link FrameLayout}
	 * flags.
	 */
	private void initViewAnimator(Context context, AttributeSet attrs) {
		if (attrs == null) {
			// For compatibility, always measure children when undefined.
			mMeasureAllChildren = true;
			return;
		}
		// TypedArray a = context.obtainStyledAttributes(attrs,
		// R.styleable.tilesFrameAnimation);
		// int resource = a.getResourceId(
		// R.styleable.tilesFrameAnimation_inAnimation, 0);
		// if (resource > 0) {
		// setInAnimation(context, resource);
		// }
		//
		// resource = a.getResourceId(
		// R.styleable.tilesFrameAnimation_outAnimation, 0);
		// if (resource > 0) {
		// setOutAnimation(context, resource);
		// }
		setAnimateFirstView(true);
		// a.recycle();
		setMeasureAllChildren(true);
	}

	/**
	 * Sets which child view will be displayed.
	 * 
	 * @param whichChild
	 *            the index of the child view to display
	 */
	public void setDisplayedChild(int whichChild) {
		mWhichChild = whichChild;
		if (whichChild >= getChildCount()) {
			mWhichChild = 0;
		} else if (whichChild < 0) {
			mWhichChild = getChildCount() - 1;
		}
		boolean hasFocus = getFocusedChild() != null;
		// This will clear old focus if we had it
		showOnly(mWhichChild);
		if (hasFocus) {
			// Try to retake focus if we had it
			requestFocus(FOCUS_FORWARD);
		}
	}

	/**
	 * Returns the index of the currently displayed child view.
	 */
	public int getDisplayedChild() {
		return mWhichChild;
	}

	/**
	 * Manually shows the next child.
	 */
	public void showNext() {
		setDisplayedChild(mWhichChild + 1);
	}

	/**
	 * Manually shows the previous child.
	 */
	public void showPrevious() {
		setDisplayedChild(mWhichChild - 1);
	}

	/**
	 * Shows only the specified child. The other displays Views exit the screen,
	 * optionally with the with the {@link #getOutAnimation() out animation} and
	 * the specified child enters the screen, optionally with the
	 * {@link #getInAnimation() in animation}.
	 * 
	 * @param childIndex
	 *            The index of the child to be shown.
	 * @param animate
	 *            Whether or not to use the in and out animations, defaults to
	 *            true.
	 */
	void showOnly(int childIndex, boolean animate) {
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View child = getChildAt(i);
			if (i == childIndex) {
				if (animate && mInAnimation != null && count > 1) {
					child.startAnimation(mInAnimation);
				}
				child.setVisibility(View.VISIBLE);
				mFirstTime = false;
			} else {
				if (animate && mOutAnimation != null
						&& child.getVisibility() == View.VISIBLE) {
					if (count > 1) {
						child.startAnimation(mOutAnimation);
					}
				} else if (child.getAnimation() == mInAnimation)
					child.clearAnimation();
				child.setVisibility(View.GONE);
			}
		}
	}

	/**
	 * Shows only the specified child. The other displays Views exit the screen
	 * with the {@link #getOutAnimation() out animation} and the specified child
	 * enters the screen with the {@link #getInAnimation() in animation}.
	 * 
	 * @param childIndex
	 *            The index of the child to be shown.
	 */
	void showOnly(int childIndex) {
		final boolean animate = (!mFirstTime || mAnimateFirstTime);
		showOnly(childIndex, animate);
	}

	@Override
	public void addView(View child, int index, ViewGroup.LayoutParams params) {
		super.addView(child, index, params);
		if (getChildCount() == 1) {
			child.setVisibility(View.VISIBLE);
		} else {
			child.setVisibility(View.GONE);
		}
		if (index >= 0 && mWhichChild >= index) {
			// Added item above current one, increment the index of the
			// displayed child
			setDisplayedChild(mWhichChild + 1);
		}
	}

	@Override
	public void removeAllViews() {
		super.removeAllViews();
		mWhichChild = 0;
		mFirstTime = true;
	}

	@Override
	public void removeView(View view) {
		final int index = indexOfChild(view);
		if (index >= 0) {
			removeViewAt(index);
		}
	}

	@Override
	public void removeViewAt(int index) {
		super.removeViewAt(index);
		final int childCount = getChildCount();
		if (childCount == 0) {
			mWhichChild = 0;
			mFirstTime = true;
		} else if (mWhichChild >= childCount) {
			// Displayed is above child count, so float down to top of stack
			setDisplayedChild(childCount - 1);
		} else if (mWhichChild == index) {
			// Displayed was removed, so show the new child living in its place
			setDisplayedChild(mWhichChild);
		}
	}

	public void removeViewInLayout(View view) {
		removeView(view);
	}

	public void removeViews(int start, int count) {
		super.removeViews(start, count);
		if (getChildCount() == 0) {
			mWhichChild = 0;
			mFirstTime = true;
		} else if (mWhichChild >= start && mWhichChild < start + count) {
			// Try showing new displayed child, wrapping if needed
			setDisplayedChild(mWhichChild);
		}
	}

	public void removeViewsInLayout(int start, int count) {
		removeViews(start, count);
	}

	/**
	 * Returns the View corresponding to the currently displayed child.
	 * 
	 * @return The View currently displayed.
	 * 
	 * @see #getDisplayedChild()
	 */
	public View getCurrentView() {
		return getChildAt(mWhichChild);
	}

	/**
	 * Returns the current animation used to animate a View that enters the
	 * screen.
	 * 
	 * @return An Animation or null if none is set.
	 * 
	 * @see #setInAnimation(android.view.animation.Animation)
	 * @see #setInAnimation(android.content.Context, int)
	 */
	public Animation getInAnimation() {
		return mInAnimation;
	}

	/**
	 * Specifies the animation used to animate a View that enters the screen.
	 * 
	 * @param inAnimation
	 *            The animation started when a View enters the screen.
	 * 
	 * @see #getInAnimation()
	 * @see #setInAnimation(android.content.Context, int)
	 */
	public void setInAnimation(Animation inAnimation) {
		mInAnimation = inAnimation;
	}

	/**
	 * Returns the current animation used to animate a View that exits the
	 * screen.
	 * 
	 * @return An Animation or null if none is set.
	 * 
	 * @see #setOutAnimation(android.view.animation.Animation)
	 * @see #setOutAnimation(android.content.Context, int)
	 */
	public Animation getOutAnimation() {
		return mOutAnimation;
	}

	/**
	 * Specifies the animation used to animate a View that exit the screen.
	 * 
	 * @param outAnimation
	 *            The animation started when a View exit the screen.
	 * 
	 * @see #getOutAnimation()
	 * @see #setOutAnimation(android.content.Context, int)
	 */
	public void setOutAnimation(Animation outAnimation) {
		mOutAnimation = outAnimation;
	}

	/**
	 * Specifies the animation used to animate a View that enters the screen.
	 * 
	 * @param context
	 *            The application's environment.
	 * @param resourceID
	 *            The resource id of the animation.
	 * 
	 * @see #getInAnimation()
	 * @see #setInAnimation(android.view.animation.Animation)
	 */
	public void setInAnimation(Context context, int resourceID) {
		setInAnimation(AnimationUtils.loadAnimation(context, resourceID));
	}

	/**
	 * Specifies the animation used to animate a View that exit the screen.
	 * 
	 * @param context
	 *            The application's environment.
	 * @param resourceID
	 *            The resource id of the animation.
	 * 
	 * @see #getOutAnimation()
	 * @see #setOutAnimation(android.view.animation.Animation)
	 */
	public void setOutAnimation(Context context, int resourceID) {
		setOutAnimation(AnimationUtils.loadAnimation(context, resourceID));
	}

	/**
	 * Returns whether the current View should be animated the first time the
	 * ViewAnimator is displayed.
	 * 
	 * @return true if the current View will be animated the first time it is
	 *         displayed, false otherwise.
	 * 
	 * @see #setAnimateFirstView(boolean)
	 */
	public boolean getAnimateFirstView() {
		return mAnimateFirstTime;
	}

	/**
	 * Indicates whether the current View should be animated the first time the
	 * ViewAnimator is displayed.
	 * 
	 * @param animate
	 *            True to animate the current View the first time it is
	 *            displayed, false otherwise.
	 */
	public void setAnimateFirstView(boolean animate) {
		mAnimateFirstTime = animate;
	}

	@Override
	public int getBaseline() {
		return (getCurrentView() != null) ? getCurrentView().getBaseline()
				: super.getBaseline();
	}

	@Override
	public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
		super.onInitializeAccessibilityEvent(event);
		event.setClassName(ViewAnimator.class.getName());
	}

	@Override
	public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
		super.onInitializeAccessibilityNodeInfo(info);
		info.setClassName(ViewAnimator.class.getName());
	}
}


备注:TileAnimator是ViewFlipper源码,只是增加了添加瓷片的类以及获取瓷片停留时间的getInterval(int next)方法。

TileAnimatorLayout是ViewAnimator的源码,唯一的不同就是增加了个数为一个时,不进行动画的判断,另外可以使TileAnimator调用showOnly(mWhichChild, flipNow)方法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值