In this tut, I present a project work like Facebook register account features, user must put data on this screen before "next" to another. Please watch this DEMO VIDEO first:
Customizing a "Disabled" ViewPager
package info.devexchanges.disabledviewpager.fragment;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class NonSwipeableViewPager extends ViewPager {
public NonSwipeableViewPager(Context context) {
super(context);
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
}
Creating an adapter with customized ViewPager
package info.devexchanges.disabledviewpager.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import info.devexchanges.disabledviewpager.fragment.NameEmailFragment;
import info.devexchanges.disabledviewpager.fragment.OtherInfoFragment;
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
if (position == 2) {
return new OtherInfoFragment();
} else {
return NameEmailFragment.getInstance(position);
}
}
@Override
public int getCount() {
return 3;
}
}
Building activities and ViewPager Fragments (pages)
After above step, we put this ViewPager object it first activity in xml layout:
In programmatically code (InputActivity.java), initialize ViewPager and set adapter like primitive:
adapter = new ViewPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter);Because of disabling swipe, we must provide a method to "next" page:
public void goToNextPage() {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
}
In Fragments, the most important problem is communicating with activity (sending data). Like "Android developer docs" say, we use Interface to pass data. With the first two pages, user will put name and email, I use a mutual Fragment and change input type by programmatically code. First, to sending data, declaring in it an Interface and create a variable with this Interface style:
private OnNameEmailChangedListener callback;
// Container Activity must implement this interface
public interface OnNameEmailChangedListener {
public void onNameEmailChanged(int position, String name);
}
Attach data to activity in onAttach():
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
callback = (OnNameEmailChangedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString());
}
}
Back to InputActivity above, it must implement OnNameEmailChangedListener and this override onNameChanged() like below:
@Override
public void onNameEmailChanged(int position, String s) {
if (position == 1) {
user.setEmail(s);
} else {
user.setName(s);
}
}
Over here, we have full code for NameEmailFragment:
>
package info.devexchanges.disabledviewpager.fragment;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.Fragment;
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import info.devexchanges.disabledviewpager.InputActivity;
import info.devexchanges.disabledviewpager.R;
public class NameEmailFragment extends Fragment {
private TextInputLayout inputLayout;
private View btnNext;
private int position;
private OnNameEmailChangedListener callback;
// Container Activity must implement this interface
public interface OnNameEmailChangedListener {
public void onNameEmailChanged(int position, String name);
}
public static Fragment getInstance(int position) {
NameEmailFragment f = new NameEmailFragment();
Bundle args = new Bundle();
args.putInt("POSITION", position);
f.setArguments(args);
return f;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_name, null, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
inputLayout = (TextInputLayout) view.findViewById(R.id.username_field);
btnNext = view.findViewById(R.id.btn_next);
position = getArguments().getInt("POSITION");
Log.i("Fragment", "" + position);
if (position == 1) {
inputLayout.getEditText().setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
inputLayout.setHint("Your Email");
}
btnNext.setOnClickListener(onNextListener());
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
callback = (OnNameEmailChangedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString());
}
}
private View.OnClickListener onNextListener() {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
if (inputLayout.getEditText().getText().toString().trim().equals("")) {
Toast.makeText(getActivity(), "Please Input your Name", Toast.LENGTH_SHORT).show();
} else {
// Notify the parent activity of selected item
callback.onNameEmailChanged(position, inputLayout.getEditText().getText().toString());
//go to next page
((InputActivity) getActivity()).goToNextPage();
}
}
};
}
}
And it's layout, use new TextInputLayout widget in Material Design tech :
And after running, this screen will like:
Similar with above steps, creating a Fragment to put age and gender:
As you can see above, in each fragment, after press Button "Next", go to next page by this code:
((InputActivity) getActivity()).goToNextPage();Full code for this page/fragment:
package info.devexchanges.disabledviewpager.fragment;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
import java.util.ArrayList;
import info.devexchanges.disabledviewpager.InputActivity;
import info.devexchanges.disabledviewpager.R;
public class OtherInfoFragment extends Fragment {
private Spinner spinner;
private TextInputLayout inputLayout;
private ArrayAdapter<String> adapter;
private ArrayList<String> genders;
private View btnNext;
private String gender;
private OnInfoChangedListener callback;
// Container Activity must implement this interface
public interface OnInfoChangedListener {
public void onInfoChanged(String age, String gender);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_other_infor, null, false);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
callback = (OnInfoChangedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString());
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
spinner = (Spinner)view.findViewById(R.id.gender);
inputLayout = (TextInputLayout)view.findViewById(R.id.age_field);
btnNext = view.findViewById(R.id.btn_next);
//set spinner adapter
genders = new ArrayList<>();
genders.add("Male");
genders.add("Female");
adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, genders);
spinner.setAdapter(adapter);
//set on item spinner selected
spinner.setOnItemSelectedListener(onItemSelectedListener());
//set click event for button
btnNext.setOnClickListener(onNextListener());
}
private View.OnClickListener onNextListener() {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
if (inputLayout.getEditText().getText().toString().trim().equals("")) {
Toast.makeText(getActivity(), "Please input your age", Toast.LENGTH_SHORT).show();
} else {
callback.onInfoChanged(inputLayout.getEditText().getText().toString(), gender);
((InputActivity) getActivity()).goToResultActivity();
}
}
};
}
private AdapterView.OnItemSelectedListener onItemSelectedListener() {
return new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView parent, View view, int position, long id) {
gender = spinner.getSelectedItem().toString();
}
@Override
public void onNothingSelected(AdapterView parent) {
}
};
}
}
Now, with one more Fragment with OnInfoChangeListener interface, InputActivity must implement it, too. We must override onInforChanged() method in it. Now, we have completed code for this activity (containing ViewPager and "collect data":
package info.devexchanges.disabledviewpager;
import android.content.Intent;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import info.devexchanges.disabledviewpager.adapter.ViewPagerAdapter;
import info.devexchanges.disabledviewpager.fragment.NameEmailFragment;
import info.devexchanges.disabledviewpager.fragment.OtherInfoFragment;
import info.devexchanges.disabledviewpager.pojo.User;
public class InputActivity extends AppCompatActivity implements NameEmailFragment.OnNameEmailChangedListener,
OtherInfoFragment.OnInfoChangedListener {
private ViewPager viewPager;
private User user;
private ViewPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
user = new User();
viewPager = (ViewPager)findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
}
public void goToNextPage() {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
}
public void goToResultActivity() {
Intent intent = new Intent(this, ResultActivity.class);
intent.putExtra("USER INFO", user);
startActivity(intent);
}
@Override
public void onNameEmailChanged(int position, String s) {
if (position == 1) {
user.setEmail(s);
} else {
user.setName(s);
}
}
@Override
public void onInfoChanged(String age, String gender) {
user.setAge(Integer.valueOf(age));
user.setGender(gender);
}
}
Coding a data receiption activity
Ouput when running:
Getting data through Intent, and set to view in programmatically code:
package info.devexchanges.disabledviewpager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import info.devexchanges.disabledviewpager.pojo.User;
public class ResultActivity extends AppCompatActivity {
private TextView name;
private TextView email;
private TextView age;
private TextView gender;
private User user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
name = (TextView) findViewById(R.id.name);
email = (TextView) findViewById(R.id.email);
age = (TextView) findViewById(R.id.age);
gender = (TextView) findViewById(R.id.gender);
//get Data from Intent
user = (User) getIntent().getExtras().getSerializable("USER INFO");
}
@Override
protected void onStart() {
super.onStart();
//set data to View
name.setText(user.getName());
email.setText(user.getEmail());
age.setText("" + user.getAge());
gender.setText(user.getGender());
}
}
Finally, this is POJO for project (User). We must implement Serializable to put this object through Intent:
package info.devexchanges.disabledviewpager.pojo;
import java.io.Serializable;
public class User implements Serializable {
private String name;
private String email;
private String gender;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Conclusion
- Read official doc to deep understand passing data in Fragment and Activity.
- Read more tuts about ViewPager by follow this tag link.
- See this post to learn how to use TextInputLayout, a Material Design widget.


