Disable Swiping on ViewPager Android

    ViewPager is widget to make swipeable screen in Android. But sometimes, in app developing, we have a feature contains a lot of screens arranged in a sequence, for example: register account. In this case, ViewPager is still used and disabled swipe is required. By this, switching pages is smoothly.
    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

   For making this trick, we can create a subclass of ViewPager, override onInterceptTouchEvent() and onTouchEvent() methods, always return false, so we have disabled swiping on our 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

    In this project, I have 3 pages for ViewPager. So, create a ViewPager adapter simple like this:
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)

    By this example, there are 2 activities: the first one contain ViewPager and use to input data and show all information to the remainding (I named them are InputActivity and ResultActivity).
    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

    In InputActivity, putting data through goToResultActivity() method. Now, make a simple layout to display this data:
    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

    In this post, I presented the way to disabled swipe in ViewPager to make the consequence screens, put and get data through Intent and communicating data between Fragment and Activity. From here, you can:
- 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.


Share


Previous post
« Prev Post
Next post
Next Post »