title: Android page control like iPhone page control
body: <p>I would like to put something back to this VERY helpful site, so this is not really a question, but rather my solution to this issue. I would also add that this solution was gleaned form support from this site and many others, so it represents the combined efforts of many other developers. To them I say thank you!</p>
  
  <p>The QUESTION is "How can you recreate the horizontal scrollView aspects of iPhone apps and the associated page control in the Android environment?"</p>
  
  <p>This arose because I wanted to display the steps in recipe, the associated method fro each step and the necessary ingredients in a single scroll view. I also wanted a page control to display to the user where they were in the steps and allow them to move to any specific step</p>
  
  <p>This part of my app displays the steps in a recipe. Each step appears on a page and has three components. A step identifier(ie. STEP 1, STEP 2), a method and a ingredients required for the step.</p>
  
  <p>Below the recipe section we display a page control that show which page is active and can be used to navigate to specific pages. You will notice that the page control has image buttons and the two images are simple circles, one for the non selected page (page.png) and one for the selected page (page_selected.png)</p>
  
  <p>When the activity is created the steps for the selected recipe are retrieved from the data and the scroller section created by adding a view for each step in the recipe. When you swipe the scroller the view snaps to the next or previous page and the pager display is updated to indicate which page you are on</p>
  
  <p>First 3 xml layouts (res/layout)</p>
  
  <p>recipe.xml</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical" &gt;
  
  &lt;RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content" &gt;
  
   &lt;!--Scroller section--&gt;
  
     &lt;HorizontalScrollView
         android:id="@+id/scroll_view"
          android:layout_width="match_parent"
          android:layout_height="320dp"
          android:layout_alignParentLeft="true"
          android:layout_alignParentTop="true"
          android:layout_marginTop="100dp" &gt;
  
              &lt;LinearLayout
                  android:id="@+id/methodScrollView"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="horizontal" &gt;
              &lt;/LinearLayout&gt;
  
      &lt;/HorizontalScrollView&gt;
  
  &lt;!-- pager section --&gt; 
  
      &lt;LinearLayout
          android:id="@+id/pager"
          android:layout_width="match_parent"
          android:layout_height="20dp"
          android:layout_alignParentLeft="true"
          android:layout_alignParentRight="true"
          android:layout_alignParentTop="true"
          android:layout_marginLeft="20dp"
          android:layout_marginRight="20dp"
          android:layout_marginTop="430dp"
          android:gravity="center"
          android:orientation="horizontal" &gt;
  
      &lt;/LinearLayout&gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p></p>
  
  <p>recipesscroll.xml (the view that will be added to the scroller section for each recipe step. Note that the scroller section has a onTouchlistner in recipeViewController.java to handle page scrolling)</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/recipeScroll"
      android:layout_width="320dp"
      android:layout_height="320dp"
      android:gravity="center_vertical" &gt;
  
     &lt;TextView
      android:id="@+id/method"
      style="@style/scrollMethod"
      android:layout_width="wrap_content"
      android:layout_height="200dp"
      android:layout_alignParentTop="true"
      android:text="Method" /&gt;
  
     &lt;TextView
      android:id="@+id/ingredients"
      style="@style/scrollIngredients"
      android:layout_width="wrap_content"
      android:layout_height="120dp"
      android:layout_alignParentTop="true"
      android:text="Ingredients" /&gt;
  
     &lt;TextView
      android:id="@+id/methodStep"
      style="@style/scrollStep"
      android:layout_width="wrap_content"
      android:layout_height="20dp"
      android:layout_alignParentTop="true"
      android:text="Step" /&gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>recipiespager.xml ( the view that will be added to the pager section for each recipe step. Note that each of these will have a onClick event in recipeViewController.java that will scroll to the specific page selected in the pager control)</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;Button xmlns:android="http://schemas.android.com/apk/res/android"
              style="@style/pageButton"
              android:layout_marginLeft="10dp"
              android:layout_width="16dp"
              android:layout_height="16dp"
              android:onClick="selectPage"&gt;
  
  &lt;/Button&gt;
  </code></pre>
  
  <p>This is all brought together in recipeViewController.java</p>
  
  <pre class="lang-java prettyprint-override"><code>//my package name change this to yours
  package com.infactdata.spinAdinner;
  
  import java.util.ArrayList;
  
  //DataModel is the model for my data change this to yours or ignore 
  because it is just away of holding the data that will populate the views
  import com.infactdata.plist.DataModel;
  
  import android.content.res.Resources;
  import android.graphics.Typeface;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.view.View.OnTouchListener;
  import android.widget.Button;
  import android.widget.HorizontalScrollView;
  import android.widget.ImageView;
  import android.widget.LinearLayout;
  import android.widget.RelativeLayout;
  import android.widget.TableLayout;
  import android.widget.TableRow;
  import android.widget.TextView;
  
  public class RecipeViewController extends RootViewController {
      private DataModel currentData;
      HorizontalScrollView h_scroll;
      int numberOfPages = 0;
      int thePage;
      int otherPage;
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
  
          //first of the xml files
          setContentView(R.layout.recipe);
  
          //reference to my global variables
          GlobalClass global = (GlobalClass)getApplicationContext();
  
          //because I wanted a particular type face
          Typeface face=Typeface.createFromAsset(getAssets(), "fonts/trebucit.ttf");
  
          //VERY IMPORTANT because we need to use this to add the content to the scroll
          and pager sections   
          LayoutInflater inflater = getLayoutInflater();
  
          //current data held a dataModel
          currentData = global.getCurrent();  
  
          currentName.setText(currentData.getName());
  
          String imageFile = currentData.getImage();
          Resources r = getResources();
  
          int res = r.getIdentifier(imageFile, "drawable", "com.infactdata.spinAdinner");
          image.setImageResource(res);
  
          //recources that change the pager indicators to different images
          thePage = r.getIdentifier("page_selected", "drawable","com.infactdata.spinAdinner");
          otherPage = r.getIdentifier("page", "drawable", "com.infactdata.spinAdinner");
  
          //Get the method(ArrayList) out of the currentData(DataModel). This is the array of 
          data that will fill the added view with different content (ie. the specific
          instructions for the recipe step. This could be your own data array.   
  
          ArrayList&lt;String[]&gt; method = new ArrayList&lt;String[]&gt;();
          method = currentData.getMethod(0);
          numberOfPages = method.size();
  
          //now to build the views by adding the content and then adding the text for that 
          content that reflects the instructions for the step in the recipe  
  
          for( int i = 0; i &lt; method.size(); i++){
  
              String[] methodStep = method.get(i);
  
              //find the scroll view
              LinearLayout scroll = (LinearLayout) findViewById(R.id.methodScrollView);
  
              //find the recipe scroller. the second xml file 
              RelativeLayout step = (RelativeLayout)findViewById(R.id.recipeScroll);
  
              //add the recipe step (step) to the scrollview (scroll)
              step = (RelativeLayout)inflater.inflate(R.layout.recipescroll, scroll, false);
  
              //add the instructions for this step in the recipe
              TextView stage = (TextView)step.findViewById(R.id.methodStep);
              stage.setText(methodStep[0].toString());
              stage.setTypeface(face);
  
              TextView methodText = (TextView)step.findViewById(R.id.method);
              methodText.setText(methodStep[1].toString());
              methodText.setTypeface(face);
  
              TextView ingredients = (TextView)step.findViewById(R.id.ingredients);
              ingredients.setText(methodStep[2].toString());
              ingredients.setTypeface(face);
  
              //create method step and add to scroll
              scroll.addView(step);
  
              //pager setup is a duplicate of the above
              //find the pager
              LinearLayout pager = (LinearLayout) findViewById(R.id.pager);
  
             //find the pager button. the third xml file
             Button page = (Button)inflater.inflate(R.layout.recipespager, pager, false);
  
             //give each button it own ID. This will be used to test which button should  be highlighted and used to move to a specific page. This is because the ID is equal to the page number (0 based of course) 
             page.setId(i);
  
             //because this is a fresh construction we will be on page 0 so highlight that button   
            if (i == 0){
                page.setBackgroundResource(thePage);
             }
  
             //create page control and add to pager
             pager.addView(page);
         }
  
        //create the onTouch controls 
  
        h_scroll = (HorizontalScrollView) findViewById(R.id.scroll_view);
        h_scroll.setOnTouchListener(scrolling);
  
   }
  
   private OnTouchListener scrolling = new OnTouchListener(){
       public boolean onTouch(View v, MotionEvent event) {
           if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == 
           MotionEvent.ACTION_CANCEL ){
               int scrollX = h_scroll.getScrollX();
               int itemWidth = h_scroll.getMeasuredWidth();
               int activePage = ((scrollX + itemWidth / 2) / itemWidth);
               int scrollTo = activePage * itemWidth;
               h_scroll.smoothScrollTo(scrollTo, 0);
  
  
               //page control display the active page button
               Log.v("MyDebug","Active page = "+activePage);
               for(int i = 0; i &lt; numberOfPages; i++){
                  Button aPage = (Button) findViewById(i);
                  if(i == activePage){
                      aPage.setBackgroundResource(thePage);
                  }else{
                      aPage.setBackgroundResource(otherPage);
                  }
               }
  
               return true;
           } else {
               return false;
           }
       }
  
   };
  
  
   //this is the onClick handler for the page buttons and moves the scroller to the page 
   associated with the button. That is through the button ID, which matches the page 
   number (0 based of course
  
   public void selectPage(View v) {
       int newPage = v.getId();
       int itemWidth = h_scroll.getMeasuredWidth();
       int scrollTo = newPage * itemWidth;
       h_scroll.smoothScrollTo(scrollTo, 0);
  
     //page control display
       Log.v("MyDebug","Active page = "+newPage);
       for(int i = 0; i &lt; numberOfPages; i++){
          Button aPage = (Button) findViewById(i);
          if(i == newPage){
              aPage.setBackgroundResource(thePage);
          }else{
              aPage.setBackgroundResource(otherPage);
          }
       }
    }
  
    public void finishActivity(View v){
        //perform back action
        finish();
    }
  
    public void nextActivity(View v){
        //move to next activity
    }
  }
  </code></pre>
  
  <p>Well that was my solution. I am certain that there are much clever programers than me out there so I am sure someone can improve this. Anyhow THANKS stackoverflow!!!!</p>