ViewFlipper,TextSwitcher

效果图:

封装:

public class GViewFlipper extends ViewFlipper {
    private Context mContext;
    //画显示器的画笔
    private Paint paint = new Paint();
    //指示器选中背景
    private int mSelectedColor = Color.BLACK;
    //指示器未选中背景
    private int mUnSelectedColor = Color.GRAY;
    //指示器显示的位置
    private GLayout mGLayout = GLayout.RIGHT_BOTTOM;
    //指示器的大小
    private int mIndicatorSize =
            getSize(10);
    //指示器间隔距离
    private int mLayoutInterval = getSize(5);
    //自动翻页
    private boolean mIsAutoFlipper;
    //默认翻页间隔3秒
    private int mFlipperInterval = 3000;
    //手势监听 请在界面显示后调用
    private OnMGestureListener mOnMGestureListener;
    private GestureDetector mGestureDetector;

    public void setmOnMGestureListener(OnMGestureListener mOnMGestureListener) {
        this.mOnMGestureListener = mOnMGestureListener;
    }

    //设置指示器显示位置
    public enum GLayout {
        CENTER_BOTTOM, RIGHT_BOTTOM
    }

    public GViewFlipper(Context context) {
        super(context);
        mContext = context;
        init(null);
    }

    public GViewFlipper(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init(attrs);
    }


    //初始化View
    private void init(AttributeSet attrs) {
        final TypedArray typeArray = mContext.obtainStyledAttributes(attrs, R.styleable.GViewFlipper);
        //初始化指示器位置
        if (typeArray.hasValue(R.styleable.GViewFlipper_mGLayout)) {
            int value = typeArray.getInt(R.styleable.GViewFlipper_mGLayout, 0);
            switch (value) {
                case 0:
                    mGLayout = GLayout.CENTER_BOTTOM;
                    break;
                case 1:
                    mGLayout = GLayout.RIGHT_BOTTOM;
                    break;
            }
        }
        if (typeArray.hasValue(R.styleable.GViewFlipper_mIndicatorSize)) {
            mIndicatorSize = (int) typeArray.getDimension(R.styleable.GViewFlipper_mIndicatorSize, mIndicatorSize);
        }
        if (typeArray.hasValue(R.styleable.GViewFlipper_mLayoutInterval)) {
            mLayoutInterval = (int) typeArray.getDimension(R.styleable.GViewFlipper_mLayoutInterval, mLayoutInterval);
        }
        if (typeArray.hasValue(R.styleable.GViewFlipper_mSelectedColor)) {
            mSelectedColor = typeArray.getColor(R.styleable.GViewFlipper_mSelectedColor, mSelectedColor);
        }
        if (typeArray.hasValue(R.styleable.GViewFlipper_mUnSelectedColor)) {
            mUnSelectedColor = typeArray.getColor(R.styleable.GViewFlipper_mUnSelectedColor, mUnSelectedColor);
        }
        if (typeArray.hasValue(R.styleable.GViewFlipper_mIsAutoFlipper)) {
            mIsAutoFlipper = typeArray.getBoolean(R.styleable.GViewFlipper_mIsAutoFlipper, mIsAutoFlipper);
        }
        if (typeArray.hasValue(R.styleable.GViewFlipper_mFlipperInterval)) {
            mFlipperInterval = typeArray.getInteger(R.styleable.GViewFlipper_mFlipperInterval, mFlipperInterval);
        }
        typeArray.recycle();
        //设置自动开始动画
        setAutoStart(mIsAutoFlipper);
        //设置动画触发间隔的时间
        setFlipInterval(mFlipperInterval);
        //设置手势
        mGestureDetector = new GestureDetector(mContext,
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                        if (e1.getX() < e2.getX()) {
                            mOnMGestureListener.onSwipeLeft();
                        }

                        if (e1.getX() > e2.getX()) {
                            mOnMGestureListener.onSwipeRight();
                        }
//                        if (e1.getY() < e2.getY()) {
//                            Timber.d("Up to Down swipe performed");
//                        }
//
//                        if (e1.getY() > e2.getY()) {
//                            Timber.d("Down to Up swipe performed");
//                        }
                        return super.onFling(e1, e2, velocityX, velocityY);
                    }
                });
    }

    //设置手势动作
    public boolean setGestureEvent(MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        int width = getWidth();

        float radius = 10;
        float cx = 0;
        if (mGLayout == GLayout.CENTER_BOTTOM) {
            cx = width / 2 - ((radius + mLayoutInterval) * 2 * getChildCount() / 2);
        }
        if (mGLayout == GLayout.RIGHT_BOTTOM) {
            cx = width - (radius + mLayoutInterval) * 2 * getChildCount() - getSize(20);
        }
        //20 距离底部20dp
        float cy = getHeight() - getSize(20);
        canvas.save();

        for (int i = 0; i < getChildCount(); i++) {
            if (i == getDisplayedChild()) {
                paint.setColor(mSelectedColor);
                canvas.drawCircle(cx, cy, radius, paint);

            } else {
                paint.setColor(mUnSelectedColor);
                canvas.drawCircle(cx, cy, radius, paint);
            }
            cx += 2 * (radius + mLayoutInterval);
        }
        canvas.restore();
    }

    private int getSize(int size) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size
                , getResources().getDisplayMetrics());
    }

    //手势监听
    public interface OnMGestureListener {
        //向左滑动
        public void onSwipeLeft();

        //向右滑动
        public void onSwipeRight();
    }
}

xml:
<com.lskj.rrhr.shortkeytest.modules.viewFilpper.GViewFlipper
    android:id="@+id/vf_test"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:mFlipperInterval="3000"
    app:mIndicatorSize="5dp"
    app:mIsAutoFlipper="true"
    app:mSelectedColor="@android:color/holo_red_dark"
    app:mUnSelectedColor="@android:color/darker_gray" />

activity:onCreate()

mViewFlipper.addView(getImageView(R.drawable.ic_test_0));
        mViewFlipper.addView(getImageView(R.drawable.ic_test_1));
        mViewFlipper.addView(getImageView(R.drawable.ic_test_2));
        mViewFlipper.addView(getImageView(R.drawable.ic_test_3));
        mViewFlipper.addView(getImageView(R.drawable.ic_test_4));
@Override
    protected void onResume() {
        super.onResume();
        mViewFlipper.setmOnMGestureListener(new GViewFlipper.OnMGestureListener() {
            @Override
            public void onSwipeLeft() {
                mViewFlipper.showPrevious();
            }

            @Override
            public void onSwipeRight() {
                mViewFlipper.showNext();
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mViewFlipper.setGestureEvent(event);
    }

 res-》values-》attrs

<declare-styleable name="GViewFlipper">
    <attr name="mSelectedColor" format="color|reference" />
    <attr name="mUnSelectedColor" format="color|reference" />
    <attr name="mGLayout" format="enum">
        <enum name="CENTER_BOTTOM" value="0" />
        <enum name="RIGHT_BOTTOM" value="1" />
    </attr>
    <attr name="mIndicatorSize" format="dimension" />
    <attr name="mLayoutInterval" format="dimension" />
    <attr name="mIsAutoFlipper" format="boolean" />
    <attr name="mFlipperInterval" format="integer" />
</declare-styleable>

参考:

http://codetheory.in/android-viewflipper-and-viewswitcher/

https://asishinwp.wordpress.com/2013/03/11/android-viewflipper-with-page-indicator/

While developing an Android application, most of us will encounter the need to integrate a section in our app where the user can switch between Views. So it should show one view which can be an ImageViewor a collection inside LinearLayoutRelativeLayout, etc. at a time that can be swiped/flinged to move to the next or previous item. Think of a slideshow of images or a step-based process like e-commerce checkouts. Basically whenever you want to swipe through a set of related sections but show only one at a time then you can leverageViewFlipper or ViewSwitcher class widgets that Android provides us. The detection of gestures can be achieved with major use of theMotionEvent class but we’ll make use of GestureDetector for this article.

ViewFlipper

So when we want to flip between two or more views, the ViewFlipperclass is what we’d most probably look at. We’ll try to create anImageView slideshow using it so let’s first define our layout resource at res/layout/activity_gesture.xml:

 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:id="@+id/relativeLayout">


    <ViewFlipper
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/viewFlipper"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

    </ViewFlipper>

</RelativeLayout>

Now obviously there are two ways to add our child views into theViewFlipper:

 
  • Add them in this layout resource itself.
  • Add them programatically.

We’ll go with the second approach in our example. Before that you might want to get 5-6 odd image resources and put them inres/drawable/ directory. Personally, I downloaded six 400×600 images from LoremPixel and shoved them into the drawable directory. For naming them I used first.pngsecond.pngthird.pngand so on.

So the immediate next thing to do is, add the image views to theViewFlipper programatically like this from the onCreate() method of our Activity:

 
private ViewFlipper mViewFlipper;
private GestureDetector mGestureDetector;

int[] resources = {
        R.drawable.first,
        R.drawable.second,
        R.drawable.third,
        R.drawable.fourth,
        R.drawable.fifth,
        R.drawable.sixth
};

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

    // Get the ViewFlipper
    mViewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper);

    // Add all the images to the ViewFlipper
    for (int i = 0; i < resources.length; i++) {
        ImageView imageView = new ImageView(this);
        imageView.setImageResource(resources[i]);
        mViewFlipper.addView(imageView);
    }
}

Now if you test your app activity in the emulator or a real handset then you’ll just see the first view. If you try to slide your fingers/mouse/pointer over the touch screen then nothing will happen. Hence, next we will integrate gesture detection using theGestureDetector class. For that we’ll first implement our custom gesture detector class as an inner class of our activity.

 
class CustomGestureDetector extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

        // Swipe left (next)
        if (e1.getX() > e2.getX()) {
            mViewFlipper.showNext();
        }

        // Swipe right (previous)
        if (e1.getX() < e2.getX()) {
            mViewFlipper.showPrevious();
        }

        return super.onFling(e1, e2, velocityX, velocityY);
    }
}

Super easy to understand code. If the initial touch X coordinate is more than the final touch X position then it was a left swipe which means the intent was to see the next picture. If it’s just the opposite then showPrevious() needs to be called on the view flipper object.

The final step is to instantiate our custom gesture detector class and then re-route all the touch events to it from our Activity’sonTouchEvent() method. The instantiation code needs to go into ouronCreate() method:

 
CustomGestureDetector customGestureDetector = new CustomGestureDetector();
mGestureDetector = new GestureDetector(this, customGestureDetector);

The onTouchEvent() implementation will be like this:

 
@Override
public boolean onTouchEvent(MotionEvent event) {
    mGestureDetector.onTouchEvent(event);

    return super.onTouchEvent(event);
}

If you test the code on your device, you’ll notice the flipping between Views work great! Congrats on building your first slideshow withViewFlipper! But the problem is there’s no animation for the flipping motion which makes the experience really bland. So let’s add a really basic fade in and fade out animation by using a couple of android’s built-in animation resources. All we have to do is add this piece of code in the onCreate() method:

 
// Set in/out flipping animations
mViewFlipper.setInAnimation(this, android.R.anim.fade_in);
mViewFlipper.setOutAnimation(this, android.R.anim.fade_out);

Wow! Now there’s some interesting transition happening when the images are swiped. So here’s how our entire activity class will be like:

 
public class GestureActivity extends Activity {

    private ViewFlipper mViewFlipper;
    private GestureDetector mGestureDetector;

    int[] resources = {
            R.drawable.first,
            R.drawable.second,
            R.drawable.third,
            R.drawable.fourth,
            R.drawable.fifth,
            R.drawable.sixth
    };

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

        // Get the ViewFlipper
        mViewFlipper = (ViewFlipper) findViewById(R.id.viewFlipper);

        // Add all the images to the ViewFlipper
        for (int i = 0; i < resources.length; i++) {
            ImageView imageView = new ImageView(this);
            imageView.setImageResource(resources[i]);
            mViewFlipper.addView(imageView);
        }

        // Set in/out flipping animations
        mViewFlipper.setInAnimation(this, android.R.anim.fade_in);
        mViewFlipper.setOutAnimation(this, android.R.anim.fade_out);

        CustomGestureDetector customGestureDetector = new CustomGestureDetector();
        mGestureDetector = new GestureDetector(this, customGestureDetector);
    }

    class CustomGestureDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

            // Swipe left (next)
            if (e1.getX() > e2.getX()) {
                mViewFlipper.showNext();
            }

            // Swipe right (previous)
            if (e1.getX() < e2.getX()) {
                mViewFlipper.showPrevious();
            }

            return super.onFling(e1, e2, velocityX, velocityY);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mGestureDetector.onTouchEvent(event);

        return super.onTouchEvent(event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.gesture, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Automatically Start Flipping

If you want to auto-start flipping then the `ViewFlipper` API gives us the ability to do so. In the onCreate() method just put this:

 
mViewFlipper.setAutoStart(true);
mViewFlipper.setFlipInterval(2000); // flip every 2 seconds (2000ms)

Setting setAutoStart() to true will automatically call startFlipping()when the view flipper is attached to the window. setFlipInterval()defines the interval between each flips in milliseconds.

You might want to add a play icon/button that should trigger the slideshow. In that case you just set a click listener on that View that’ll trigger startFlipping() while the stop button will call stopFlipping().

Custom Sliding Flipping Animations

Instead of the built-in android animations we can also write our own animation XML resources and apply that to the transition. Let’s see how to write a simple one where the images will slide in and out of the screen on swipe. We’ll create four animation resources for:

  • Next image to come into screen (left_in.xml) and current image to move out from the left (left_out.xml) on swiping to left.
  • Previous image to come into screen (right_in.xml) and current image to move out from the right (right_out.xml) on swiping to the right.

Code for res/anim/left_in.xml:

 
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="100%p"
        android:toXDelta="0" />

    <alpha
        android:duration="500"
        android:fromAlpha="0.1"
        android:toAlpha="1.0" />

</set>

Code for res/anim/left_out.xml:

 
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="0"
        android:toXDelta="-100%p" />

    <alpha
        android:duration="500"
        android:fromAlpha="1.0"
        android:toAlpha="0.1" />
</set>

Code for res/anim/right_in.xml:

 
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="-100%p"
        android:toXDelta="0" />

    <alpha
        android:duration="500"
        android:fromAlpha="0.1"
        android:toAlpha="1.0" />

</set>

Code for res/anim/right_out.xml:

 
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="500"
        android:fromXDelta="0"
        android:toXDelta="100%p" />

    <alpha
        android:duration="500"
        android:fromAlpha="1.0"
        android:toAlpha="0.1" />

</set>

Now in the Activity class’s onCreate() method remove thesetInAnimation() and setOutAnimation() method calls on the view flipper object. We’ll need them in the if blocks of our custom gesture detector class’s onFling() method. Here’s how our new custom gesture detector will look like after setting the new animation resources:

 
class CustomGestureDetector extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

        // Swipe left (next)
        if (e1.getX() > e2.getX()) {
            mViewFlipper.setInAnimation(GestureActivity.this, R.anim.left_in);
            mViewFlipper.setOutAnimation(GestureActivity.this, R.anim.left_out);

            mViewFlipper.showNext();
        }

        // Swipe right (previous)
        if (e1.getX() < e2.getX()) {
            mViewFlipper.setInAnimation(GestureActivity.this, R.anim.right_in);
            mViewFlipper.setOutAnimation(GestureActivity.this, R.anim.right_out);

            mViewFlipper.showPrevious();
        }

        return super.onFling(e1, e2, velocityX, velocityY);
    }
}

Test it out in your device or emulator. You’ll enjoy some nice sliding effects while flipping over images in the slideshow.

Instead of using gestures to switch between views, you can also have buttons with click listeners that’d fire the mViewFlipper.showNext()and mViewFlipper.showPrevious() actions.

ViewSwitcher

By now if you’ve properly understood ViewFlipper then ViewSwitcherwill be a piece of cake for you. Just like ViewFlipperViewSwitcher is also a ViewAnimator (they are sub classes of ViewAnimator) that can hold only two child views (only significant difference with view flipper feature-wise) and show one at a time. We can add child views to it just like we did with our ViewFlipper or use its factory to create the views.

If we add Views like we did in the previous case:

 
// Get the ViewFlipper
mViewSwitcher = (ViewSwitcher) findViewById(R.id.viewSwitcher);

// Add all the images to the ViewFlipper
for (int i = 0; i < resources.length; i++) {
    ImageView imageView = new ImageView(this);
    imageView.setImageResource(resources[i]);
    mViewSwitcher.addView(imageView);
}

This will work fine as long as resources has only 2 items, else it’ll throw an exception with the message

 

java.lang.IllegalStateException: Can't add more than 2 views to a ViewSwitcher.

Instead of calling addView() twice we can also call setFactory() on the ViewSwitcher object to set the factory that’d create the two views between which the user will switch (although I’d just prefer callingaddView() two times).

 
mViewSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
    @Override
    public View makeView() {
        ImageView imageView = new ImageView(GestureActivity.this);
        imageView.setImageResource(resources[0]);

        // Log.d(TAG, "setFactory#makeView");

        return imageView;
    }
});

The makeView() method will get called twice to generate two views. In this case it’s using the same resource as the image so we’ll have to set some condition (maybe based on mViewSwitcher.getChildCount()) to make sure that the second time some other resource is selected for the second view.

Here’s how your Activity making use of ViewSwitcher would look like (pretty much similar to the previous example using ViewFlipper):

 
public class GestureActivity extends Activity {

    // private ViewFlipper mViewFlipper;
    private ViewSwitcher mViewSwitcher;
    private GestureDetector mGestureDetector;

    int[] resources = {
            R.drawable.first,
            R.drawable.second/*,
            R.drawable.third,
            R.drawable.fourth,
            R.drawable.fifth,
            R.drawable.sixth*/
    };

    private String TAG = GestureActivity.class.getSimpleName();

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

        // Get the ViewFlipper
        mViewSwitcher = (ViewSwitcher) findViewById(R.id.viewSwitcher);

        /*mViewSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
            @Override
            public View makeView() {
                ImageView imageView = new ImageView(GestureActivity.this);
                imageView.setImageResource(resources[0]);

                Log.d(TAG, "setFactory#makeView");

                return imageView;
            }
        });*/

        // Add all the images to the ViewFlipper
        for (int i = 0; i < resources.length; i++) {
            ImageView imageView = new ImageView(this);
            imageView.setImageResource(resources[i]);
            mViewSwitcher.addView(imageView);
        }

        // Set in/out flipping animations
        //mViewFlipper.setInAnimation(this, android.R.anim.fade_in);
        //mViewFlipper.setOutAnimation(this, android.R.anim.fadeout);

        CustomGestureDetector customGestureDetector = new CustomGestureDetector();
        mGestureDetector = new GestureDetector(this, customGestureDetector);
    }

    class CustomGestureDetector extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

            // Swipe left (next)
            if (e1.getX() > e2.getX()) {
                mViewSwitcher.setInAnimation(GestureActivity.this, R.anim.left_in);
                mViewSwitcher.setOutAnimation(GestureActivity.this, R.anim.left_out);

                mViewSwitcher.showNext();
            }

            // Swipe right (previous)
            if (e1.getX() < e2.getX()) {
                mViewSwitcher.setInAnimation(GestureActivity.this, R.anim.right_in);
                mViewSwitcher.setOutAnimation(GestureActivity.this, R.anim.right_out);

                mViewSwitcher.showPrevious();
            }

            /*mViewSwitcher.getInAnimation().setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    Log.d(TAG, "Animation End");
                    Log.d(TAG, "Child Count: " + mViewSwitcher.getChildCount());
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });*/

            return super.onFling(e1, e2, velocityX, velocityY);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mGestureDetector.onTouchEvent(event);

        return super.onTouchEvent(event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.gesture, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Off the bat, one use of ViewSwitcher that I can think of is cases when you’ll need to have login and registration forms or maybe after the login submit button is clicked, the second view can show a loader or some confirmation message.

Differences Between ViewFlipper and ViewSwitcher

I came across these two classes when I really needed to transform one view to another for a specific requirement in my app which is similar to an image slideshow. Now based on the knowledge we’ve since we covered both of them in fair amount of details, the only difference between these two classes is that, ViewSwitcher supports only two views while ViewFlipper can have multiple. Also ViewSwitcher can source its views from a factory which has to be set via setFactory().

In most cases we’ll probably just want to use ViewFlipper over the other one.

Conclusion

These widgets are pretty nifty when a specific requirement entails moving between/among various Views. Although for my requirement I ended up using ViewPager because I really wanted its style of sliding transition where once the current image is pulled to the left the next one is also drawn along with it. Until a certain threshold if you release the image (or the View) then it’ll get back to its original state and the next View will move off the screen from the right edge.

If you’ve any questions regarding these view animators then feel free to discuss in the comments section.

添加圆型指示器:

Android ViewFlipper with page indicator.

Make a subclass of ViewFlipper and override “dispatchDraw(Canvas canvas)” method. Draw circle (rect, bitmap anything you like) in the bottom/upper of the viewFlipper.

public class AViewFlipper extends ViewFlipper
{

Paint paint = new Paint();

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

@Override
protected void dispatchDraw(Canvas canvas)
{
super.dispatchDraw(canvas);
int width = getWidth();

float margin = 2;
float radius = 5;
float cx = width / 2 – ((radius + margin) * 2 * getChildCount() / 2);
float cy = getHeight() – 15;

canvas.save();

for (int i = 0; i < getChildCount(); i++)
{
if (i == getDisplayedChild())
{
paint.setColor(Color.BLUE);
canvas.drawCircle(cx, cy, radius, paint);

} else
{
paint.setColor(Color.GRAY);
canvas.drawCircle(cx, cy, radius, paint);
}
cx += 2 * (radius + margin);
}
canvas.restore();
}

}

That’s it, plot this view in xml.

<packageName.AViewFlipper

android:layout_width=”fill_parent”

android:layout_height=”@dimen/menubody_height”>

<include layout=”@layout/layout1″ />

<include layout=”@layout/layout2″ />

<include layout=”@layout/layout3″ />

</packageName.AViewFlipper>

添加手势 实现左右滑动 :

final GestureDetector mGestureDetector = new GestureDetector(mContext,
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (e1.getX() < e2.getX()) {
mOnMGestureListener.onSwipeLeft();
}

if (e1.getX() > e2.getX()) {
mOnMGestureListener.onSwipeRight();
}
// if (e1.getY() < e2.getY()) {
// Timber.d("Up to Down swipe performed");
// }
//
// if (e1.getY() > e2.getY()) {
// Timber.d("Down to Up swipe performed");
// }
return super.onFling(e1, e2, velocityX, velocityY);
}
});
mGestureDetector.onTouchEvent(event);
原文地址:https://www.cnblogs.com/ClodThunder/p/5926722.html