ViewPager で入力画面を作る

android.support.v4.view.ViewPager で以下のように android:uiOptions="splitActionBarWhenNarrow" の画面を作る。

最初のページ

f:id:posturan:20160313193916p:plain



最後のページ(横にした時で、入力が終わってないので FINISH が非活性)

f:id:posturan:20160313193910p:plain



全て入力後の最後のページ

f:id:posturan:20160313193904p:plain



これを作る場合、単純に View のスライドでは3ページ以上の構成で1ページ目(最後から前の前のページ)の入力は Viewが破棄されて入力値は保持されない。

少し手間でも Fragment を使った方が簡単に入力値の保持が可能だ。

呼び出し元の Activity に入力値を返す前提でサンプルを作ると以下のようになる。



import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;

public class SwipeInputAcrtivity extends Activity{
   static int REQUEST_CODE = 1;
   static String FIRST_NAME = "firstName";
   static String LAST_NAME  = "lastName";
   static String EMAIL      = "email";
   static String PHONE      = "phone";

   private ViewPager mPager;
   private PagerAdapter mPagerAdapter;
   List<Fragment> fragmentList;

   @Override
   protected void onCreate(Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
      setContentView(R.layout.swipe_main_2);
      // 入力 Slide ページ Fragment 生成
      createPage();

      
      mPager = (ViewPager)findViewById(R.id.pager);
      
      mPagerAdapter = new FragmentStatePagerAdapter(getFragmentManager()){
         @Override
         public Fragment getItem(int position){
            return fragmentList.get(position);
         }
         @Override
         public int getCount(){
            return fragmentList.size();
         }
      };
      mPager.setAdapter(mPagerAdapter);
      mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
         @Override
         public void onPageSelected(int position){
            invalidateOptionsMenu();
         }
      });
   }
   private void createPage(){
      fragmentList = new ArrayList<Fragment>();
      Bundle args = new Bundle();
      // 必要に応じて Bundle で渡したいものを渡す
      fragmentList.add(Input1stPage.create(args));
      fragmentList.add(Input2ndPage.create(args));
      fragmentList.add(Input3rdPage.create(args));
   }

   private Menu _menu;
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      super.onCreateOptionsMenu(menu);
      this._menu = menu;
      getMenuInflater().inflate(R.menu.activity_screen_slide, menu);
      menu.findItem(R.id.action_previous).setEnabled(mPager.getCurrentItem() > 0);
      MenuItem item;
      if (mPager.getCurrentItem()==(mPagerAdapter.getCount() - 1)){
         item = menu.add(Menu.NONE, R.id.action_next , Menu.NONE, R.string.action_finish );
         menu.findItem(R.id.action_next).setEnabled(isInputComplete());
      }else{
         item = menu.add(Menu.NONE, R.id.action_next , Menu.NONE, R.string.action_next );
      }
      item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);

      return true;
   }
   // 最後のページの Fragment で Menu を制御するために Menu の getterを用意する。
   public Menu getMenu(){
      return _menu;
   }

   @Override
   public boolean onOptionsItemSelected(MenuItem item){
      switch (item.getItemId()) {
      case R.id.action_previous:
         mPager.setCurrentItem(mPager.getCurrentItem() - 1);
         return true;
      case R.id.action_next:
         int currentItem = mPager.getCurrentItem();
         mPager.setCurrentItem(currentItem + 1);
         // 最後のページで押された時は、
         if (currentItem==2){
            Input1stPage input1stPage = (Input1stPage)fragmentList.get(0);
            String firstName = input1stPage.getFirstName();
            String lastName = input1stPage.getFirstName();
            String email = *1.getEmail();
            String phone = *2.getPhoneNumber();
            Intent i = new Intent();
            i.putExtra(FIRST_NAME, firstName);
            i.putExtra(LAST_NAME, lastName);
            i.putExtra(EMAIL, email);
            i.putExtra(PHONE, phone);
            setResult(Activity.RESULT_OK, i);
            // Abtivity の終了
            finish();
         }

         return true;
      }
      return super.onOptionsItemSelected(item);
   }
   // 必須チェック
   public boolean isInputComplete(){
      Input1stPage input1stPage = (Input1stPage)fragmentList.get(0);
      if (input1stPage.getFirstName().trim().length()==0) return false;
      if (input1stPage.getFirstName().trim().length()==0) return false;
      if (((Input2ndPage)fragmentList.get(1)).getEmail().trim().length()==0) return false;
      if (((Input3rdPage)fragmentList.get(2)).getPhoneNumber().trim().length()==0) return false;
      return true;
   }

}
-------------- 最初のページ  ------------------------
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
/**
 * Input1stPage
 */

public class Input1stPage extends Fragment{
   private EditText firstNameEditText;
   private EditText lastNameEditText;


   public static Input1stPage create(Bundle args){
      Input1stPage fragment = new Input1stPage();
      fragment.setArguments(args);
      return fragment;
   }
   public Input1stPage(){}


   @Override
   public void onCreate(Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
      setRetainInstance(true);
   }
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
      setRetainInstance(true);
      ViewGroup viewGroup = (ViewGroup)inflater.inflate(R.layout.swipe_sub_1, container, false);
      firstNameEditText = (EditText)viewGroup.findViewById(R.id.firstNameEditText);
      lastNameEditText = (EditText)viewGroup.findViewById(R.id.lastNameEditText);
      return viewGroup;

   }
   @Override
   public void onActivityCreated(Bundle savedInstanceState){
      super.onActivityCreated(savedInstanceState);
      setRetainInstance(true);
   }
   public String getFirstName(){
      return firstNameEditText.getText().toString();
   }
   public String getLastName(){
      return lastNameEditText.getText().toString();
   }

}

同様に最後までのページを用意するが、最後のページの入力で全ての入力チェックとして Activiy で用意する
入力チェックを呼び、Menu の enable 属性を制御する。

   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
      setRetainInstance(true);
      ViewGroup viewGroup = (ViewGroup)inflater.inflate(R.layout.swipe_sub_3, container, false);
      phoneNumEditText = (EditText)viewGroup.findViewById(R.id.phoneNumEdditText);
      phoneNumEditText.addTextChangedListener(new TextWatcher(){
         @Override
         public void onTextChanged(CharSequence s, int start, int before, int count){
         }
         @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after){
         }
         @Override
         public void afterTextChanged(Editable s){
            *3.getMenu().findItem(R.id.action_next).setEnabled(
                  *4.isInputComplete()
            );
         }
      }
);
      return viewGroup;
   }

*1:Input2ndPage)fragmentList.get(1

*2:Input3rdPage)fragmentList.get(2

*3:SwipeInputAcrtivity)getActivity(

*4:SwipeInputAcrtivity)getActivity(