Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correctly implementing PagerAdapter in Android

I have problems with implementation of my custom PagerAdapter and using it with a ViewPager. This sample PagerAdapter has 10 items, every item is a button with it's index as text. When I run my program, I see a button with text '1' insted of '0'. And when I swipe to other items I get only blank views. When I swipe backwards sometimes I see a button with some number, but it disappears (maybe it is destroying and I remove it from the container), and sometimes I see a button with a number, but the number changes after the swipe (I think I create a new Button and I add it to the container, and for some reasons the viewpager shows this new button).

How can I fix this implementation? I haven't seen difference in examples.

My PagerAdapter implementation:

public class MyPagerAdapter extends PagerAdapter {

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public boolean isViewFromObject(View view, Object o) {
        return o.getClass()==view.getClass();
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Button button = new Button(container.getContext());
        ViewGroup.LayoutParams params = new ActionBar.LayoutParams(-1,-1);
        button.setLayoutParams(params);
        button.setText(String.valueOf(position));
        container.addView(button);
        return button;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((Button)object);
    }
}

And my Activity:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager pager = (ViewPager) findViewById(R.id.pager);
        pager.setAdapter(new MyPagerAdapter());
    }
}
like image 308
oriskop Avatar asked Feb 06 '15 00:02

oriskop


People also ask

What is the use of PagerAdapter in Android?

A PagerAdapter may implement a form of View recycling if desired or use a more sophisticated method of managing page Views such as Fragment transactions where each page is represented by its own Fragment. ViewPager associates each page with a key Object instead of working with Views directly.

How the ViewPager is implemented?

Implement Swipe Views You can create swipe views using AndroidX's ViewPager widget. To use ViewPager and tabs, you need to add a dependency on ViewPager and on Material Components to your project. To insert child views that represent each page, you need to hook this layout to a PagerAdapter .

What is PagerAdapter?

Implementation of PagerAdapter that represents each page as a Fragment that is persistently kept in the fragment manager as long as the user can return to the page. FragmentStatePagerAdapter. Implementation of PagerAdapter that uses a Fragment to manage each page.


2 Answers

Here is complete code:

xml layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidviewpagerapp.MainActivity" >

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

MyPagerAdapter class:

import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

public class MyPagerAdapter extends PagerAdapter {

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public boolean isViewFromObject(View view, Object o) {
        return o==view;
    }

    @Override
    public Object instantiateItem(final ViewGroup container, int position) {
        Button button = new Button(container.getContext());
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        button.setLayoutParams(params);
        button.setText(String.valueOf(position));

        final int page = position;
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(container.getContext(), "You clicked: " + page + ". page.", Toast.LENGTH_SHORT).show();
            }
        });

        container.addView(button);
        return button;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((Button)object);
    }
}

MainActivity:

import android.support.v4.view.ViewPager;
import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {
    ViewPager viewPager;
    MyPagerAdapter myPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = (ViewPager)findViewById(R.id.pager);
        myPagerAdapter = new MyPagerAdapter();
        viewPager.setAdapter(myPagerAdapter);
    }
}

You will see that Buttons are full screen. To avoid that you need to create some layout (like LinearLayout) and add button to that layout.

Example:

import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MyPagerAdapter extends PagerAdapter {

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public boolean isViewFromObject(View view, Object o) {
        return o==view;
    }

    @Override
    public Object instantiateItem(final ViewGroup container, int position) {
        Button button = new Button(container.getContext());
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        button.setLayoutParams(params);
        button.setText(String.valueOf(position));

        LinearLayout layout = new LinearLayout(container.getContext());
        layout.setOrientation(LinearLayout.VERTICAL);
        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

        //add buton to layout
        layout.addView(button);

        final int page = position;
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(container.getContext(), "You clicked: " + page + ". page.", Toast.LENGTH_SHORT).show();
            }
        });
        //to container add layout instead of button
        container.addView(layout);
        //return layout instead of button
        return layout;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        //cast to LinearLayout
        container.removeView((LinearLayout)object);
    }
}
like image 147
633kM Avatar answered Nov 03 '22 00:11

633kM


if you want to inflate views in pager you must have to implement two methods. instantiateItem and destroyItem

public class DialogPagerAdapter extends PagerAdapter {

    private Context mContext;

    //view inflating..
    @Override
    public Object instantiateItem(ViewGroup collection, int position) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.account_dialog_signin_viewpagers,
                collection, false);

        TextView tvLabel = (TextView) layout.findViewById(R.id.textView);
        switch (position) {
            case 0:
                tvLabel.setText("Log In");
                tvLabel.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                    }
                });
                break;
            case 1:
                tvLabel.setText("Sign Up");
                tvLabel.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                    }
                });
                break;
            case 2:
                tvLabel.setText("Send Reset Link");
                tvLabel.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        //onOptionClickForgot.OnOptionClick();
                    }
                });
                break;
        }

        collection.addView(layout);
        return layout;
    }

    @Override
    public void destroyItem(ViewGroup collection, int position, Object view) {
        collection.removeView((View) view);
}

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

Simply call it like

viewPager.setAdapter(new DialogPagerAdapter);

xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dialog_button_height"
    android:paddingLeft="@dimen/dimen_2"
    android:paddingRight="@dimen/dimen_2"
    android:minHeight="@dimen/dialog_button_height">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/app_name"
        android:textColor="@color/white"
        android:textSize="@dimen/text_size_medium" />
</RelativeLayout>
like image 21
Zar E Ahmer Avatar answered Nov 03 '22 02:11

Zar E Ahmer