Wednesday, July 4, 2012

Flipping Views in Android


Let’s face it: phones are small.
Even if you have a phone with excellent screen resolution, the physical screen size is still rarely over 3″x5″, since most people want phones that can fit in a pocket, purse, pouch, or poncho.
This means your Android activities can only display so much stuff at one time without individual widgets or text getting too small to be easily read. There are any number of ways to handle this:
  • You could break the one activity into several…but this can get cumbersome
  • You can use ScrollView to allow users to scroll through a longer activity…but this may or may not be easy for the user depending on the device (e.g., a haptic interface using a swipe for scrolling assumes there’s a place clear in the UI for them to actually swipe without accidentally toggling a button or something)
  • You can use TabView, as described in the previous post…but you are locked into a particular presentation pattern (e.g., tabs)
  • You can use ViewFlipper and work out a UI pattern that’s right for you
Not surprisingly, today, we’re going to look at the latter option.
ViewFlipper inherits from FrameLayout, just like we used to describe the innards of a TabView in that previous post. However, initially, it just shows the first child view. It is up to you to arrange for the views to flip, either manually by user interaction, or automatically via a timer.
For example, here is a layout for a simple activity using a Button and a ViewFlipper:
  1. xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <Button android:id="@+id/flip_me"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:text="Flip Me!"
  11. />
  12. <ViewFlipper android:id="@+id/details"
  13. android:layout_width="fill_parent"
  14. android:layout_height="fill_parent"
  15. >
  16. <TextView
  17. android:layout_width="fill_parent"
  18. android:layout_height="wrap_content"
  19. android:textStyle="bold"
  20. android:textColor="#FF00FF00"
  21. android:text="This is the first panel"
  22. />
  23. <TextView
  24. android:layout_width="fill_parent"
  25. android:layout_height="wrap_content"
  26. android:textStyle="bold"
  27. android:textColor="#FFFF0000"
  28. android:text="This is the second panel"
  29. />
  30. <TextView
  31. android:layout_width="fill_parent"
  32. android:layout_height="wrap_content"
  33. android:textStyle="bold"
  34. android:textColor="#FFFFFF00"
  35. android:text="This is the third panel"
  36. />
  37. ViewFlipper>
  38. LinearLayout>
Notice that the layout defines three child views for the ViewFlipper, each a TextView with a simple message. Of course, you could have very complicated child views, if you so chose.
To manually flip the views, we need to hook into the Button and flip them ourselves when the button is clicked:
  1. public class FlipperDemo extends Activity {
  2. ViewFlipper flipper;
  3. @Override
  4. public void onCreate(Bundle icicle) {
  5. super.onCreate(icicle);
  6. setContentView(R.layout.main);
  7. flipper=(ViewFlipper)findViewById(R.id.details);
  8. Button btn=(Button)findViewById(R.id.flip_me);
  9. btn.setOnClickListener(new View.OnClickListener() {
  10. public void onClick(View view) {
  11. flipper.showNext();
  12. }
  13. });
  14. }
  15. }
This is just a matter of calling showNext() on the ViewFlipper, like you can on any ViewAnimator class.
The result is a trivial activity: click the button, and the next TextView in sequence is displayed, wrapping around to the first after viewing the last:
ViewFlipper demo, on the first view
Same demo, next view, after clicking button
This, of course, could be handled more simply by having a single TextView and changing the text and color on each click. However, you can imagine that the ViewFlipper contents could be much more complicated, like the contents you might put into a TabView.
As with the TabView in the previous post, sometimes, your ViewFlipper contents may not be known at compile time. As with TabView, though, you can add new contents on the fly with ease.
For example, let’s look at another sample activity, using this layout:
  1. xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <ViewFlipper android:id="@+id/details"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent"
  10. >
  11. ViewFlipper>
  12. LinearLayout>
Notice that the ViewFlipper has no contents at compile time. Also note that there is no Button for flipping between the contents — more on this in a moment.
For the ViewFlipper contents, we will create large Button widgets, each containing one of the random words used in many an Android tutorial. And, we will set up the ViewFlipper to automatically rotate between the Button widgets, using an animation for transition:
  1. public class FlipperDemo2 extends Activity {
  2. static String[] items={"lorem", "ipsum", "dolor", "sit", "amet",
  3. "consectetuer", "adipiscing", "elit",
  4. "morbi", "vel", "ligula", "vitae",
  5. "arcu", "aliquet", "mollis", "etiam",
  6. "vel", "erat", "placerat", "ante",
  7. "porttitor", "sodales", "pellentesque",
  8. "augue", "purus"};
  9. ViewFlipper flipper;
  10. @Override
  11. public void onCreate(Bundle icicle) {
  12. super.onCreate(icicle);
  13. setContentView(R.layout.main);
  14. flipper=(ViewFlipper)findViewById(R.id.details);
  15. flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));
  16. flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out));
  17. for (String item : items) {
  18. Button btn=new Button(this);
  19. btn.setText(item);
  20. flipper.addView(btn,
  21. new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
  22. ViewGroup.LayoutParams.FILL_PARENT));
  23. }
  24. flipper.setFlipInterval(2000);
  25. flipper.startFlipping();
  26. }
  27. }
After getting our ViewFlipper widget from the layout, we first set up the “in” and “out” animations. In Android terms, an animation is a description of how a widget leaves (”out”) or enters (”in”) the viewable area. Animations are a complex beast, worthy of a blog post or two in their own right. For now, realize that animations are resources, stored in res/anim/ in your project. For this tutorial, we are using a pair of animations supplied by the SDK samples, available under the Apache 2.0 license. As their names suggest, widgets are “pushed” to the left, either to enter or leave the viewable area.
After iterating over the funky words, turning each into a Button, and adding the Button as a child of the ViewFlipper, we set up the flipper to automatically flip between children (flipper.setFlipInterval(2000);) and to start flipping (flipper.startFlipping();).
The result is an endless series of buttons, each appearing, then sliding out to the left after 1.5 seconds, being replaced by the next button in sequence, wrapping around to the first after the last has been shown:

In this case, the above screenshot shows the ViewFlipper in mid-transition, animating away from one button to the next.
The auto-flipping ViewFlipper is useful for status panels or other situations where you have a lot of information to display, but not much room. The key is that, since it automatically flips between views, expecting users to interact with individual views is dicey — the view might switch away part-way through their interaction.

No comments:

Post a Comment