Cách triển khai ViewPager với các mảnh / bố cục khác nhau


191

Khi tôi bắt đầu một hoạt động thực hiện chế độ xem, trình xem đó đã tạo ra các đoạn khác nhau. Tôi muốn sử dụng các bố cục khác nhau cho mỗi phân đoạn, nhưng vấn đề là viewpager chỉ hiển thị hai bố cục ở mức tối đa (bố cục thứ hai trên tất cả các phân đoạn còn lại sau 1).

Đây là mã cho SwipeActivity thực hiện chế độ xem:

public class SwipeActivity extends FragmentActivity
{

    MyPageAdapter pageAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_swipe);
        pageAdapter = new MyPageAdapter(getSupportFragmentManager());
        ViewPager pager=(ViewPager)findViewById(R.id.pager);
        pager.setAdapter(pageAdapter);
        ActionBar bar = getActionBar();
        bar.setDisplayHomeAsUpEnabled(true);
    }
    /**
    * Custom Page adapter
    */
    private class MyPageAdapter extends FragmentPagerAdapter
    {
        public MyPageAdapter(FragmentManager fm)
        {
            super(fm);
        }
        @Override
        public int getCount()
        {
            return 5;
        }
        @Override
        public Fragment getItem(int position)
        {
            switch(position)
            {
                case 0: return new MyFragment();
                case 1: return SecondFragment.newInstance("asdasd");
                default : return RamFragment.newInstance("s");
            }
        }
     }
}

Đây là mã cho các mảnh

public class MyFragment extends Fragment
{
   @Override
   public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup,    Bundle paramBundle)
   {
     return paramLayoutInflater.inflate(R.layout.processorlayout, paramViewGroup, false);
   }
}

Tôi đã sử dụng 5 đoạn như thế này, tất cả đều có bố cục khác nhau, nhưng chế độ xem chỉ hiển thị tối đa 2.

EDIT : mã cho SecondFragment

public class SecondFragment extends Fragment
{
   public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";

  public static final SecondFragment newInstance(String paramString)
  {
    SecondFragment f = new SecondFragment();
    Bundle localBundle = new Bundle(1);
    localBundle.putString("EXTRA_MESSAGE", paramString);
    f.setArguments(localBundle);
    return f;
  }

  @Override
  public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle)
  {
     return paramLayoutInflater.inflate(R.layout.motherboardlayout, paramViewGroup, false);
  }
}

Tôi đang nhận được một lỗi không khớp loại. Bạn có thể xem bài viết của tôi? stackoverflow.com/questions/28334800/
Mạnh


Vấn đề của mã của bạn là gì?
dùng1510006

Xin chào bạn có thể đọc bài viết này câu trả lời rất đơn giản với mã hoàn chỉnh được cung cấp.
Nirmal Dhara

Câu trả lời:


516

Vì đây là một câu hỏi rất thường gặp, tôi muốn dành thời gian và nỗ lực để giải thích ViewPager với nhiều Mảnh vỡ và Bố cục chi tiết. Bạn đi đây

ViewPager với nhiều tệp Fragment và Layout - Cách thực hiện

Sau đây là một ví dụ đầy đủ về cách triển khai ViewPager với các loại phân đoạn khác nhau và các tệp bố cục khác nhau.

Trong trường hợp này, tôi có 3 lớp Fragment và một tệp bố cục khác nhau cho mỗi lớp. Để giữ cho mọi thứ đơn giản, bố cục mảnh chỉ khác nhau về màu nền của chúng . Tất nhiên, bất kỳ tệp bố cục nào cũng có thể được sử dụng cho Fragment.

FirstFragment.java có bố cục nền màu cam , SecondFragment.java có bố cục nền màu xanh lá cây và ThirdFragment.java có bố cục nền màu đỏ . Hơn nữa, mỗi Fragment hiển thị một văn bản khác nhau, tùy thuộc vào nó thuộc lớp nào và nó thuộc trường hợp nào.

Ngoài ra, hãy lưu ý rằng tôi đang sử dụng Fragment của thư viện hỗ trợ: android.support.v4.app.Fragment

MainActivity.java (Khởi tạo Viewpager và có bộ điều hợp cho nó như một lớp bên trong). Một lần nữa có một cái nhìn vào hàng nhập khẩu . Tôi đang sử dụng android.support.v4gói.

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class MainActivity extends FragmentActivity {

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

        ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
        pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
    }

    private class MyPagerAdapter extends FragmentPagerAdapter {

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int pos) {
            switch(pos) {

            case 0: return FirstFragment.newInstance("FirstFragment, Instance 1");
            case 1: return SecondFragment.newInstance("SecondFragment, Instance 1");
            case 2: return ThirdFragment.newInstance("ThirdFragment, Instance 1");
            case 3: return ThirdFragment.newInstance("ThirdFragment, Instance 2");
            case 4: return ThirdFragment.newInstance("ThirdFragment, Instance 3");
            default: return ThirdFragment.newInstance("ThirdFragment, Default");
            }
        }

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

Activity_main.xml (Tệp MainActivitys .xml) - một tệp bố cục đơn giản, chỉ chứa ViewPager lấp đầy toàn màn hình.

<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    />

Các lớp Fragment, FirstFragment.java nhập android.support.v4.app.Fragment;

public class FirstFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.first_frag, container, false);

        TextView tv = (TextView) v.findViewById(R.id.tvFragFirst);
        tv.setText(getArguments().getString("msg"));

        return v;
    }

    public static FirstFragment newInstance(String text) {

        FirstFragment f = new FirstFragment();
        Bundle b = new Bundle();
        b.putString("msg", text);

        f.setArguments(b);

        return f;
    }
}

First_frag.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_orange_dark" >

    <TextView
        android:id="@+id/tvFragFirst"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="26dp"
        android:text="TextView" />
</RelativeLayout>

Thứ haiFragment.java

public class SecondFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.second_frag, container, false);

    TextView tv = (TextView) v.findViewById(R.id.tvFragSecond);
    tv.setText(getArguments().getString("msg"));

    return v;
}

public static SecondFragment newInstance(String text) {

    SecondFragment f = new SecondFragment();
    Bundle b = new Bundle();
    b.putString("msg", text);

    f.setArguments(b);

    return f;
}
}

second_frag.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_green_dark" >

    <TextView
        android:id="@+id/tvFragSecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="26dp"
        android:text="TextView" />

</RelativeLayout>

Thứ baFragment.java

public class ThirdFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.third_frag, container, false);

    TextView tv = (TextView) v.findViewById(R.id.tvFragThird);      
    tv.setText(getArguments().getString("msg"));

    return v;
}

public static ThirdFragment newInstance(String text) {

    ThirdFragment f = new ThirdFragment();
    Bundle b = new Bundle();
    b.putString("msg", text);

    f.setArguments(b);

    return f;
}
}

third_frag.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_red_light" >

    <TextView
        android:id="@+id/tvFragThird"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:textSize="26dp"
        android:text="TextView" />

</RelativeLayout>

Kết quả cuối cùng là như sau:

Viewpager chứa 5 Fragment, Fragment 1 thuộc loại FirstFragment và hiển thị bố cục First_frag.xml, Fragment 2 thuộc loại SecondFragment và hiển thị second_frag.xml và Fragment 3-5 thuộc loại ThirdFragment và tất cả đều hiển thị third_frag.xml .

nhập mô tả hình ảnh ở đây

Ở trên, bạn có thể thấy 5 Đoạn giữa có thể được chuyển qua vuốt sang trái hoặc phải. Tất nhiên chỉ có một mảnh vỡ có thể được hiển thị cùng một lúc.

Cuối cùng nhưng không kém phần quan trọng:

Tôi khuyên bạn nên sử dụng một hàm tạo trống trong mỗi lớp Fragment của bạn.

Thay vì bàn giao các tham số tiềm năng thông qua hàm tạo, hãy sử dụng newInstance(...)phương thức và Bundleđể bàn giao các tham số.

Cách này nếu tách rời và gắn lại trạng thái đối tượng có thể được lưu trữ thông qua các đối số. Giống như Bundlesgắn liền với Intents.


7
@PhilippJahoda câu trả lời tuyệt vời, cảm ơn. Tuy nhiên, tôi muốn đề cập đến một điều, nếu ViewPager được xác định trong Fragment hơn getSupportChildFragmentManager () nên được sử dụng thay vì getSupportFragmentManager () khi tạo bộ điều hợp. Nếu không, mã bị phá vỡ khi thay đổi định hướng xảy ra.
chàng.gc

5
Vâng, đó là chính xác. Nhưng trong ví dụ của tôi, ViewPager được định nghĩa trong một Hoạt động và do đó, getSupportFragmentManager () là phù hợp. Hơn nữa, phương thức getSupportChildFragmentManager () không tồn tại, tôi giả sử bạn đang tham khảo getChildFragmentManager ().
Philipp Jahoda

1
Bạn có thể sử dụng ViewPager với các đoạn gốc khi sử dụng gói hỗ trợ v13. developer.android.com/reference/android/support/v13/app/ từ
Philipp Jahoda

1
kể từ Android Lollipop 5.0, điều này có còn hợp lệ không?
Orkun Ozen

5
Trong phương thức MyPagerAd CHƯƠNG -> getItem (int pos) của bạn, bạn luôn nhận được một phiên bản mới của đoạn đích (dựa trên giá trị pos). Vì vậy, mỗi khi bạn xoay thiết bị của mình (thay đổi hướng), phương thức getItem được gọi và các đoạn được tạo ra nhiều lần. Nhưng chúng được lưu trữ trong trình quản lý phân đoạn khi tạo. Tôi nghĩ bạn nên kiểm tra xem họ đã có trong trình quản lý phân đoạn chưa vì nếu bạn không lãng phí bộ nhớ. Xem pastebin.com/0bJc9mHA
rekt0x

8

Tạo một mảng Lượt xem và áp dụng nó vào: container.addView(viewarr[position]);

public class Layoutes extends PagerAdapter {

    private Context context;
    private LayoutInflater layoutInflater;
    Layoutes(Context context){
        this.context=context;
    }
    int layoutes[]={R.layout.one,R.layout.two,R.layout.three};
    @Override
    public int getCount() {
        return layoutes.length;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return (view==(LinearLayout)object);
    }
    @Override
    public Object instantiateItem(ViewGroup container, int position){
        layoutInflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View one=layoutInflater.inflate(R.layout.one,container,false);
        View two=layoutInflater.inflate(R.layout.two,container,false);
        View three=layoutInflater.inflate(R.layout.three,container,false);
        View viewarr[]={one,two,three};
        container.addView(viewarr[position]);
        return viewarr[position];
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object){
        container.removeView((LinearLayout) object);
    }

}

Chúng tôi có thể tăng cường bố cục trong ViewPager bằng cách tạo mảng khung nhìn.
akash ingle

6

Mã để thêm đoạn

public Fragment getItem(int position) {

    switch (position){
        case 0:
            return new Fragment1();

        case 1:
            return new Fragment2();

        case 2:
            return new Fragment3();

        case 3:
            return new Fragment4();

        default:
            break;
    }

    return null;
}

Tạo một tệp xml cho mỗi phân đoạn nói cho Fragment1, sử dụng Fragment_one.xml làm tệp bố cục, sử dụng mã dưới đây trong tệp java Fragment1.

public class Fragment1 extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_one, container, false);

        return view;

    }
}

Sau này bạn có thể sửa chữa cần thiết .. Nó đã làm việc cho tôi.


4

Ví dụ về ViewPager cơ bản

Câu trả lời này là một sự đơn giản hóa của tài liệu , hướng dẫn nàycâu trả lời được chấp nhận . Mục đích của nó là để làm việc ViewPagervà chạy càng nhanh càng tốt. Chỉnh sửa thêm có thể được thực hiện sau đó.

nhập mô tả hình ảnh ở đây

XML

Thêm bố cục xml cho hoạt động chính và cho mỗi trang (đoạn). Trong trường hợp của chúng tôi, chúng tôi chỉ sử dụng một bố cục phân đoạn, nhưng nếu bạn có bố cục khác nhau trên các trang khác nhau thì chỉ cần tạo một bố cục cho mỗi trang.

Activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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"
    tools:context="com.example.verticalviewpager.MainActivity">

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

</RelativeLayout>

Fragment_one.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textview"
        android:textSize="30sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true" />

</RelativeLayout>

Đây là mã cho hoạt động chính. Nó bao gồm PagerAdapterFragmentOnenhư các lớp bên trong. Nếu chúng quá lớn hoặc bạn đang tái sử dụng chúng ở những nơi khác, thì bạn có thể di chuyển chúng đến các lớp riêng biệt của chúng.

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class MainActivity extends AppCompatActivity {

    static final int NUMBER_OF_PAGES = 2;

    MyAdapter mAdapter;
    ViewPager mPager;

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

        mAdapter = new MyAdapter(getSupportFragmentManager());
        mPager = findViewById(R.id.viewpager);
        mPager.setAdapter(mAdapter);
    }

    public static class MyAdapter extends FragmentPagerAdapter {
        public MyAdapter(FragmentManager fm) {
            super(fm);
        }

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

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return FragmentOne.newInstance(0, Color.WHITE);
                case 1:
                    // return a different Fragment class here
                    // if you want want a completely different layout
                    return FragmentOne.newInstance(1, Color.CYAN);
                default:
                    return null;
            }
        }
    }

    public static class FragmentOne extends Fragment {

        private static final String MY_NUM_KEY = "num";
        private static final String MY_COLOR_KEY = "color";

        private int mNum;
        private int mColor;

        // You can modify the parameters to pass in whatever you want
        static FragmentOne newInstance(int num, int color) {
            FragmentOne f = new FragmentOne();
            Bundle args = new Bundle();
            args.putInt(MY_NUM_KEY, num);
            args.putInt(MY_COLOR_KEY, color);
            f.setArguments(args);
            return f;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mNum = getArguments() != null ? getArguments().getInt(MY_NUM_KEY) : 0;
            mColor = getArguments() != null ? getArguments().getInt(MY_COLOR_KEY) : Color.BLACK;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_one, container, false);
            v.setBackgroundColor(mColor);
            TextView textView = v.findViewById(R.id.textview);
            textView.setText("Page " + mNum);
            return v;
        }
    }
}

Đã kết thúc

Nếu bạn đã sao chép và dán ba tệp ở trên vào dự án của mình, bạn sẽ có thể chạy ứng dụng và xem kết quả trong hình động ở trên.

Đang xảy ra

Có khá nhiều thứ bạn có thể làm với ViewPager. Xem các liên kết sau để bắt đầu:


3

Điều này cũng tốt:

<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    />
public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
        pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));

    }
}


public class FragmentTab1 extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragmenttab1, container, false);
        return rootView;
    }
}

class MyPagerAdapter extends FragmentPagerAdapter{

    public MyPagerAdapter(FragmentManager fragmentManager){
        super(fragmentManager);

    }
    @Override
    public android.support.v4.app.Fragment getItem(int position) {
        switch(position){
            case 0:
                FragmentTab1 fm =   new FragmentTab1();
                return fm;
            case 1: return new FragmentTab2();
            case 2: return new FragmentTab3();
        }
        return null;
    }

    @Override
    public int getCount() {
        return 3;
    }
}
<RelativeLayout 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" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="@string/Fragment1" />

</RelativeLayout>

0

Tạo các thể hiện mới trong các đoạn của bạn và làm như vậy trong Hoạt động của bạn

 private class SlidePagerAdapter extends FragmentStatePagerAdapter {
    public SlidePagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        switch(position){
            case 0:
                return Fragment1.newInstance();
            case 1:
                return Fragment2.newInstance();
            case 2:
                return Fragment3.newInstance();
            case 3:
                return Fragment4.newInstance();


            default: break;

        }
        return null;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.