ViewFlipper 实现幻灯片功能
来源:互联网 发布:成都gis软件培训班 编辑:程序博客网 时间:2024/05/20 23:29
ViewFlipper实现幻灯片非常容易,下面我们先来看看代码是怎么实现功能的.
布局也很简单:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ViewFlipper android:id="@+id/viewFlipper" android:layout_width="match_parent" android:layout_height="match_parent" > </ViewFlipper></LinearLayout>
就一个ViewFlipper控件就好了. 代码如下:
import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.view.animation.AnimationUtils;import android.widget.ImageView;import android.widget.ImageView.ScaleType;import android.widget.ViewFlipper;import com.example.testdemo.R;public class MainActivity extends Activity implements OnClickListener {private ViewFlipper flipper;private int[] urls = { R.drawable.c, R.drawable.g, R.drawable.h,R.drawable.i, R.drawable.j, R.drawable.k, R.drawable.o };@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);flipper = (ViewFlipper) findViewById(R.id.viewFlipper);flipper.setOnClickListener(this);//启动startSlide();}private void startSlide() {//设置进入动画flipper.setInAnimation(AnimationUtils.loadAnimation(this,R.anim.slide_left_in));//设置退出动画flipper.setOutAnimation(AnimationUtils.loadAnimation(this,R.anim.slide_left_out));addFlipperView();}private void addFlipperView() {for (int i = 0; i < urls.length; i++) {ImageView iv = new ImageView(this);iv.setScaleType(ScaleType.CENTER_INSIDE);iv.setBackgroundResource(urls[i]);flipper.addView(iv);}//开始flipper.startFlipping();//指定从那个位置开始flipper.setDisplayedChild(0);}@Overridepublic void onClick(View v) {//停止幻灯片flipper.stopFlipping();//移除flipper中所有的图片flipper.removeAllViews();}}
这是这么简单,很容易的实现了换灯片功能.看看ViewFlipper源码中它继承了ViewAnimator类,
源码如下:
@RemoteViewpublic class ViewFlipper extends ViewAnimator { private static final String TAG = "ViewFlipper"; private static final boolean LOGD = false; private static final int DEFAULT_INTERVAL = 3000; 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; public ViewFlipper(Context context) { super(context); } public ViewFlipper(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewFlipper); mFlipInterval = a.getInt( com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL); mAutoStart = a.getBoolean( com.android.internal.R.styleable.ViewFlipper_autoStart, false); a.recycle(); } 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(); // Listen for broadcasts related to user-presence final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); // OK, this is gross but needed. This class is supported by the // remote views machanism and as a part of that the remote views // can be inflated by a context for another user without the app // having interact users permission - just for loading resources. // For exmaple, when adding widgets from a user profile to the // home screen. Therefore, we register the receiver as the current // user not the one the context is for. getContext().registerReceiverAsUser(mReceiver, android.os.Process.myUserHandle(), filter, null, mHandler); if (mAutoStart) { // Automatically start when requested 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 */ @android.view.RemotableViewMethod 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); mHandler.sendMessageDelayed(msg, mFlipInterval); } else { mHandler.removeMessages(FLIP_MSG); } mRunning = running; } if (LOGD) { Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning); } } /** * Returns true if the child views are flipping. */ public boolean isFlipping() { return mStarted; } /** * Set if this view automatically calls {@link #startFlipping()} when it * becomes attached to a window. */ public void setAutoStart(boolean autoStart) { mAutoStart = autoStart; } /** * 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); sendMessageDelayed(msg, mFlipInterval); } } } };}
源码中我们很清楚的看出ViewFlipper中运用了广播实现了切换的交互,具体功能和设置属性可想而知是在ViewAnimator类中实现的我们来看看ViewAnimator类的源码:
public class ViewAnimator extends FrameLayout { int mWhichChild = 0; boolean mFirstTime = true; boolean mAnimateFirstTime = true; Animation mInAnimation; Animation mOutAnimation; public ViewAnimator(Context context) { super(context); initViewAnimator(context, null); } public ViewAnimator(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewAnimator); int resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_inAnimation, 0); if (resource > 0) { setInAnimation(context, resource); } resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_outAnimation, 0); if (resource > 0) { setOutAnimation(context, resource); } boolean flag = a.getBoolean(com.android.internal.R.styleable.ViewAnimator_animateFirstView, true); setAnimateFirstView(flag); a.recycle(); initViewAnimator(context, attrs); } /** * 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; } // For compatibility, default to measure children, but allow XML // attribute to override. final TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout); final boolean measureAllChildren = a.getBoolean( com.android.internal.R.styleable.FrameLayout_measureAllChildren, true); setMeasureAllChildren(measureAllChildren); a.recycle(); } /** * Sets which child view will be displayed. * * @param whichChild the index of the child view to display */ @android.view.RemotableViewMethod 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. */ @android.view.RemotableViewMethod public void showNext() { setDisplayedChild(mWhichChild + 1); } /** * Manually shows the previous child. */ @android.view.RemotableViewMethod 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) { child.startAnimation(mInAnimation); } child.setVisibility(View.VISIBLE); mFirstTime = false; } else { if (animate && mOutAnimation != null && child.getVisibility() == View.VISIBLE) { 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()); }}
在ViewAnimator类中它继承了FrameLayout,这里我们就能明白他是用碎片来做切换的,源码还是比较简单的,都是一些设置属性的方法,比如setDisplayedChild(0)设置启动位置,setInAnimation()设置进入的动画,setOutAnimation()设置出去的动画等方法.看完源码我们现在是不是更清楚的知道ViewFlipper控件真的是为幻灯片连身定制的,但是有个问题就是图片多了容易报内存溢出.希望能帮助大大家.
动画效果可以自由设置,下面是从右到左的切换,先在res文件夹中创建一个anim文件夹在anim文件夹中创建xml文件选择set属性;R.anim.slide_left_in代码如下:
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 画面转换位置移动动画效果 开始向左动画 fromXDelta : 动画开始时 X坐标位置 toXDelta :动画结束时 X坐标位置 duration :动画持续时间 --> <translate android:duration="800" android:fromXDelta="100%p" android:toXDelta="0" /></set>
R.anim.slide_left_out代码如下:
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="800" android:fromXDelta="0" android:toXDelta="-100%p" /></set>
0 0
- ViewFlipper 实现幻灯片功能
- ViewFlipper实现简单的幻灯片效果
- viewflipper实现幻灯片的简单播放
- 使用ViewPager实现幻灯片播放功能
- 用Literal来填充脚本,实现幻灯片等功能
- 动态实现幻灯片功能(应用filters.revealTrans)
- 如何实现MindMapper中的幻灯片功能的合理运用
- ViewFlipper的功能和用法
- ViewFlipper的功能和用法
- Android ViewFlipper 功能与用法
- ViewFlipper实现图片动画
- viewFlipper的基本实现
- ViewFlipper 实现翻页动画
- ViewFlipper实现滑动翻页
- 左右滑动---viewflipper实现
- ViewFlipper实现滑动翻页
- ViewFlipper实现手势滑动
- ViewFlipper实现引导页面
- Power management interface(PM API)
- ios NSURLSession使用说明及后台工作流程分析
- 顺序结构(数组)线性表
- python之pandas(一)
- 使用jdom解析XML文件 ,转自163博客
- ViewFlipper 实现幻灯片功能
- css链接地址 base href
- 人脸识别技术大总结1——Face Detection & Alignment
- 链式结构线性表
- iOS网络编程(六)NSURLSession详解
- Application received signal SIGSEGV
- Fedora, CentOS 查看网关地址
- 四季
- .Net用UploadFile控件上传文件受到大小限制的解决办法