Richtige Implementierung von ViewPager2 in Android


76

Ich habe ViewPager2 kennengelernt und versucht, es zu implementieren, aber kein geeignetes Beispiel gefunden.

Kann mir jemand sagen, wie ich es benutzen kann.

Ich suche die richtige Verwendung, kein Beispiel.


6
Hier ist Erklärung und Beispiel überprüfen Sie es: michaelevans.org/blog/2019/02/07/hands-on-with-viewpager2
Mehul Kabaria

3
Wer auch immer enge Stimmen abgegeben hat recommend or find a book, tool, software library, tutorial or other off-site resourceBitte lesen Sie sorgfältig, dass ich nicht nach Beispiel suche.
Pratik Butani


1
geschätzte Frage, sehen aus wie Blog: D
Nikunj Paradva

@NikunjParadva Antwort von Nilesh Rathod wird sehr geschätzt und sieht auch aus wie ein Blog-Beitrag. Die Frage ist einfach.
Pratik Butani

Antworten:


178

UPDATE 7

Überprüfen Sie: Migrieren Sie von ViewPager zu ViewPager2

Aktivieren : Erstellen Sie mit ViewPager2 Swipe-Ansichten mit Registerkarten

UPDATE 6

Schauen Sie sich meine Antwort an, wenn Sie Carousel mit View Pager2 implementieren möchten

UPDATE 5

Verwendung von TabLayout mit ViewPager2

BEISPIELCODE

Verwenden Sie unten dependencies

implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'

BEISPIELCODE

XMl-Layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewpager"
            app:layout_anchor="@id/tabs"
            app:layout_anchorGravity="bottom"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
    />


</androidx.coordinatorlayout.widget.CoordinatorLayout>

Aktivität

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import com.google.android.material.tabs.TabLayoutMediator

import com.google.android.material.tabs.TabLayout


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

//        setSupportActionBar(toolbar)
        viewpager.adapter = AppViewPagerAdapter(supportFragmentManager, lifecycle)

        TabLayoutMediator(tabs, viewpager, object : TabLayoutMediator.OnConfigureTabCallback {
            override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
                // Styling each tab here
                tab.text = "Tab $position"
            }
        }).attach()


    }
}

AUSGABE

TabLayout mit ViewPager2

Aus Dokumenten

ViewPager2

Neue Eigenschaften

  • Unterstützung für das Layout von rechts nach links (RTL)
  • Unterstützung für vertikale Ausrichtung
  • notifyDataSetChanged voll funktionsfähig

API-Änderungen

  • FragmentStateAdapter ersetzt FragmentStatePagerAdapter
  • RecyclerView.Adapter ersetzt PagerAdapter
  • registerOnPageChangeCallback ersetzt addPageChangeListener

BEISPIELCODE

füge das Neueste dependenciesfür hinzuViewPager2

implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha01'

Layout

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Aktivität

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;

import java.util.ArrayList;

public class MyActivity extends AppCompatActivity {

    ViewPager2 myViewPager2;
    MyAdapter MyAdapter;
    private ArrayList<String> arrayList = new ArrayList<>();

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

        myViewPager2 = findViewById(R.id.view_pager);

        arrayList.add("Item 1");
        arrayList.add("Item 2");
        arrayList.add("Item 3");
        arrayList.add("Item 4");
        arrayList.add("Item 5");

        MyAdapter = new MyAdapter(this, arrayList);


        myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);

        myViewPager2.setAdapter(MyAdapter);
    }
}

MyAdapter

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    private Context context;
    private ArrayList<String> arrayList = new ArrayList<>();

    public MyAdapter(Context context, ArrayList<String> arrayList) {
        this.context = context;
        this.arrayList = arrayList;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.tvName.setText(arrayList.get(position));
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tvName;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            tvName = itemView.findViewById(R.id.tvName);
        }
    }
}

Neue Eigenschaften

Jetzt müssen wir verwenden ViewPager2.OnPageChangeCallback(), um Swipe-Ereignis von zu bekommenViewPager2

BEISPIELCODE

    myViewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            super.onPageScrolled(position, positionOffset, positionOffsetPixels);
        }

        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);

            Log.e("Selected_Page", String.valueOf(position));
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            super.onPageScrollStateChanged(state);
        }
    });

Wir können die Ausrichtung mit einstellen myViewPager2.setOrientation()

BEISPIELCODE

Zur HORIZONTAL OrientationVerwendung

myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);

Zur VERTICAL OrientationVerwendung

myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);

Wir können notifyDataSetChangeddasselbe verwenden, wie wir es in verwendenRecyclerView.Adapter

BEISPIELCODE zum Hinzufügen eines neuen Elements

    btnAdd.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            arrayList.add("New ITEM ADDED");
            MyAdapter.notifyDataSetChanged();
        }
    });

BEISPIELCODE zum Entfernen eines neuen Elements

    btnRemove.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            arrayList.remove(3);
            MyAdapter.notifyItemRemoved(3);
        }
    });

AKTUALISIEREN

Versuchen Sie dies , wenn Sie verwenden möchten , FragmentmitViewPager2

Erstellen Sie zuerst eine ViewPagerFragmentAdapterKlasse, die erweitert wirdFragmentStateAdapter

import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager2.adapter.FragmentStateAdapter;

public class ViewPagerFragmentAdapter extends FragmentStateAdapter {

    private ArrayList<Fragment> arrayList = new ArrayList<>();

    public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return arrayList.get(position);
    }

    public void addFragment(Fragment fragment) {
        arrayList.add(fragment);
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }
}

Verwenden Sie dies jetzt in Ihrer Aktivität

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import neel.com.bottomappbar.R;

public class MainActivity extends AppCompatActivity {

    ViewPager2 myViewPager2;
    ViewPagerFragmentAdapter myAdapter;

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

        myViewPager2 = findViewById(R.id.view_pager);

        myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager());

        // add Fragments in your ViewPagerFragmentAdapter class
        myAdapter.addFragment(new FragmentOne());
        myAdapter.addFragment(new Fragmenttwo());
        myAdapter.addFragment(new FragmentThree());

        // set Orientation in your ViewPager2
        myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);

        myViewPager2.setAdapter(myAdapter);

    }

}

Weitere Informationen finden Sie hier

UPDATE 2

Version 1.0.0-alpha02

Neue Eigenschaften

  • Möglichkeit zur Deaktivierung von Benutzereingaben ( setUserInputEnabled, isUserInputEnabled)

API-Änderungen

  • ViewPager2 Klassenfinale

Fehlerbehebung

  • FragmentStateAdapter Stabilitätskorrekturen

BEISPIELCODE zum Deaktivieren des Wischens in viewpager2

myViewPager2.setUserInputEnabled(false);// SAMPLE CODE to disable swiping in viewpager2


myViewPager2.setUserInputEnabled(true);//SAMPLE CODE to enable swiping in viewpager2

UPDATE 3

Version 1.0.0-alpha03

Neue Eigenschaften

  • Möglichkeit zum programmgesteuerten Scrollen von ViewPager2: fakeDragBy (offsetPx) .

API-Änderungen

  • FragmentStateAdaptererfordert jetzt ein LifecycleObjekt. Zwei Dienstprogrammkonstruktoren wurden hinzugefügt, um es vom Host FragmentActivityoder vom Hostfragment zu erhalten

BEISPIELCODE

ViewPagerFragmentAdapter

import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;

public class ViewPagerFragmentAdapter extends FragmentStateAdapter {

    private ArrayList<Fragment> arrayList = new ArrayList<>();


    public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
        super(fragmentManager, lifecycle);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return arrayList.get(position);
    }

    public void addFragment(Fragment fragment) {
        arrayList.add(fragment);
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }
}

MainActivity-Code

import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import neel.com.bottomappbar.R;

public class MainActivity extends AppCompatActivity {

    ViewPager2 myViewPager2;
    ViewPagerFragmentAdapter myAdapter;

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

        myViewPager2=findViewById(R.id.view_pager);
        myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager(), getLifecycle());

        // add Fragments in your ViewPagerFragmentAdapter class
        myAdapter.addFragment(new FragmentOne());
        myAdapter.addFragment(new Fragmenttwo());
        myAdapter.addFragment(new FragmentThree());

        myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);

        myViewPager2.setAdapter(myAdapter);
    }
}

UPDATE 4

Version 1.0.0-alpha05 Neue Eigenschaften

  • ItemDecoratoreingeführt mit einem Verhalten im Einklang mit RecyclerView.
  • MarginPageTransformer eingeführt, um Platz zwischen Seiten zu schaffen (außerhalb des Seiteneinsatzes).
  • CompositePageTransformer eingeführt, um die Möglichkeit zu bieten, mehrere zu kombinieren PageTransformers

API-Änderungen

  • FragmentStateAdapter#getItemMethode umbenannt in FragmentStateAdapter#createFragment- Der vorherige Methodenname hat sich in der Vergangenheit als Fehlerquelle erwiesen.
  • OFFSCREEN_PAGE_LIMIT_DEFAULTWert von 0 auf -1 geändert. Keine Notwendigkeit für eine Client-Code-Änderung, wenn der OFFSCREEN_PAGE_LIMIT_DEFAULTconstantverwendet wird.

BEISPIELCODE

Aktivitätscode

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.MarginPageTransformer;
import androidx.viewpager2.widget.ViewPager2;
import neel.com.bottomappbar.R;

public class MainActivity extends AppCompatActivity {

    ViewPager2 myViewPager2;
    ViewPagerFragmentAdapter myAdapter;
    private ArrayList<Fragment> arrayList = new ArrayList<>();

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

        myViewPager2 = findViewById(R.id.myViewPager2);

        // add Fragments in your ViewPagerFragmentAdapter class
        arrayList.add(new FragmentOne());
        arrayList.add(new Fragmenttwo());
        arrayList.add(new FragmentThree());

        myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager(), getLifecycle());
        // set Orientation in your ViewPager2
        myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);

        myViewPager2.setAdapter(myAdapter);

        myViewPager2.setPageTransformer(new MarginPageTransformer(1500));


    }
}

ViewPagerFragmentAdapter

import java.util.ArrayList;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;

public class ViewPagerFragmentAdapter extends FragmentStateAdapter {

    private ArrayList<Fragment> arrayList = new ArrayList<>();


    public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
        super(fragmentManager, lifecycle);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position) {
            case 0:
                return new FragmentOne();
            case 1:
                return new Fragmenttwo();
            case 2:
                return new FragmentThree();

        }
        return null;
    }

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

12
Es scheint, als
müsste

1
Super, ich habe keine Zeit für Blogpost bekommen, aber ich werde es auf jeden Fall tun.
Pratik Butani

1
Frühe Einführung von ViewPager2 durch @BirjuVachhani, überprüfen Sie dies, es könnte nützlich sein
Ravi

2
Ist es möglich, ViewPager2 zu verwenden PagerTitleStripoder PagerTabStripmit oder gibt es eine Alternative?
Guillaume

1
@NileshRathod, Sie haben eine Arrayliste mit Fragmenten erstellt, rufen sie aber nirgendwo auf?
Eingabe

6

Derzeit gibt es ein offizielles Beispiel-Repo für ViewPager2 (unten verlinkt)

Repo enthält folgende Beispiele (Zitat aus der Repo-Readme-Datei unten)

Proben

  • ViewPager2 mit Ansichten - zeigt, wie Sie einen ViewPager2 mit Ansichten als Seiten einrichten
  • ViewPager2 mit Fragmenten - zeigt, wie Sie einen ViewPager2 mit Fragmenten als Seiten einrichten
  • ViewPager2 mit einer veränderlichen Sammlung (Ansichten) - Veranschaulicht die Verwendung von ViewPager2 mit Ansichten als Seiten und Mutationen in einem Seitenadapter
  • ViewPager2 mit einer veränderlichen Sammlung (Fragmente) - Veranschaulicht die Verwendung von ViewPager2 mit Fragmenten als Seiten und Mutationen in einem Seitenadapter
  • ViewPager2 mit einem TabLayout (Ansichten) - zeigt, wie Sie einen ViewPager2 mit Ansichten als Seiten einrichten und mit einem TabLayout verknüpfen

Einfaches Beispiel für ViewPager2 mit Fragmenten in Kotlin

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager2_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        val viewPager2 = findViewById<ViewPager2>(R.id.pager2_container)

        val fragmentList = arrayListOf(
            FirstFragment.newInstance(),
            SecondFragment.newInstance(),
            ThirdFragment.newInstance()
        )
        viewPager2.adapter = ViewPagerAdapter(this, fragmentList)
   }
}

FirstFragment.kt ( SecondFragment.ktund ThirdFragment.ktsieht ähnlich aus FirstFragment.kt)

class FirstFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    companion object{
        fun newInstance() = FirstFragment()
    }
}

ViewPagerAdapter.kt

class ViewPagerAdapter(fa:FragmentActivity, private val fragments:ArrayList<Fragment>): FragmentStateAdapter(fa) {

    override fun getItemCount(): Int = fragments.size

    override fun createFragment(position: Int): Fragment = fragments[position]

}

Einige andere nützliche Ressourcen:


3

Verwendung von ViewPager2 in Android

Wie auf der Entwicklerseite erwähnt

API-Änderungen

FragmentStateAdapter ersetzt FragmentStatePagerAdapter

RecyclerView.Adapter ersetzt PagerAdapter

registerOnPageChangeCallback ersetzt addPageChangeListener

In einfachen Worten funktioniert der View Pager-Adapter wie der Recycle View Adapter.

Hinweis: - In View Pager 2 muss kein Fragment verwendet werden. Es hängt vollständig vom RecyclerView.Adapter-Inflate-Layout ab.

Hier ist ein Beispiel für einen gitHub Repo Link

Beispiel:-

MainActivity.class

public class MainActivity extends AppCompatActivity {
    
    private ViewPager2 mPager;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getSupportActionBar().setTitle("View Pager 2");
        mPager = findViewById(R.id.pager);
        mPager.setAdapter(new MyViewPagerAdapter(this));
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (R.id.change == item.getItemId()) {
            mPager.setOrientation(mPager.getOrientation() != ViewPager2.ORIENTATION_VERTICAL ? ViewPager2.ORIENTATION_VERTICAL : ViewPager2.ORIENTATION_HORIZONTAL);
        }
        return super.onOptionsItemSelected(item);
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.constraint.ConstraintLayout>

MyViewPagerAdapter.class

public class MyViewPagerAdapter extends RecyclerView.Adapter<MyHolder> {
    
    private Context context;
    
    public MyViewPagerAdapter(Context context) {
        this.context=context;
    }
    
    @NonNull
    @Override
    public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new MyHolder(LayoutInflater.from(context).inflate(R.layout.cell_item, parent, false));
    }
    
    @Override
    public void onBindViewHolder(@NonNull MyHolder holder, int position) {
      holder.mText.setText("Page "+(position+1));
    }
    
    @Override
    public int getItemCount() {
        return 10;
    }
}

cell_item.xml

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

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Page 1"
        android:textSize="20sp" />

</android.support.constraint.ConstraintLayout>

MyHolder.class

class MyHolder extends RecyclerView.ViewHolder {
    
    public TextView mText;
    
    public MyHolder(@NonNull View itemView) {
        super(itemView);
        mText = itemView.findViewById(R.id.text);
    }
}

Ausgabe:

Geben Sie hier die Bildbeschreibung ein


Können wir ViewPager2 nicht mit Fragmenten verwenden?
Ysfcyln

@ysfcyln ja Sie können Fragmentmit verwenden ViewPager2, überprüfen Sie bitte meine obige Antwort Ich habe Beispielcode fürHow use Fragment with ViewPager2
AskNilesh

Danke, aber das Repository wird gelöscht.
CoolMind

@CoolMind Welches Repository wird gelöscht?
Sushildlh


3

Folgendes habe ich getan, um ViewPager2 mit TabLayout mit 3 Fragmenten zu implementieren. Vollständiges Beispiel:

Layout enthält ViewPager2mit TabLayout:

 <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/include3">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:background="@color/colorPrimary"
            app:tabTextColor="@color/tab_dismiss_color"
            app:tabSelectedTextColor="@color/green"
            android:layout_height="wrap_content" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_gravity="bottom"
            android:background="#e4e4e4" />

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    </LinearLayout>

Starten Sie ViewPager2 und legen Sie den Tab-Namen fest:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_report);
        ButterKnife.bind(this);
        actionBarTitleId.setText(R.string.reports);

        viewPager.setAdapter(new ViewPagerAdapter(this));

        new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
            switch (position) {
                case 0:
                    tab.setText(R.string.financial_duty_str);
                    break;
                case 1:
                    tab.setText(R.string.financial_unpaid_str);
                    break;
                case 2:
                    tab.setText(R.string.financial_paid_str);
                    break;

            }
        }).attach();

    }

ViewPager2 Adapter:

public class ViewPagerAdapter extends FragmentStateAdapter {


    public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position) {
            case 0:
                return new FinancialFragment();
            case 1:
                return new FinancialUnPaidFragment();
            case 2:
                return new FinancialPaidFragment();
            default:
                return null;

        }
    }

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

verwendete Abhängigkeit:

implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation 'com.google.android.material:material:1.1.0-alpha10'

0

Hier meine Lösung (Android Studio 3.6):

In app / build.gradle:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') { transitive = true; }
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.google.android.material:material:1.1.0-beta01'
    implementation 'org.altbeacon:android-beacon-library:2.16.3'
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
    implementation 'androidx.viewpager2:viewpager2:1.0.0-beta05'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation "androidx.core:core-ktx:+"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

Hier meine Tätigkeit:

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.widget.ViewPager2;

import java.util.ArrayList;
import java.util.List;

import com.myproject.android.R;
import com.myproject.android.adapter.CustomFragmentStateAdapter;
import com.myproject.android.ui.fragment.BluetoothPageFragment;
import com.myproject.android.ui.fragment.QrPageFragment;

public class QRBluetoothSwipeActivity extends AppCompatActivity {
    private ViewPager2 myViewPager2;
    private CustomFragmentStateAdapter myAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        // Make sure this is before calling super.onCreate
        setTheme(R.style.AppTheme); // show splash screen
        super.onCreate(savedInstanceState);
        setContentView(R.layout.qr_bluetooth_swipe_activity);
        init();
    }

    private void init() {
        List<Fragment> fragmentList = new ArrayList<Fragment>();
        QrPageFragment m1 = new QrPageFragment();
        BluetoothPageFragment m2 = new BluetoothPageFragment();
        myViewPager2 = findViewById(R.id.viewPager2);
        fragmentList.add(m2);
        fragmentList.add(m1);
        myAdapter = new CustomFragmentStateAdapter(this, fragmentList);
        myViewPager2.setAdapter(myAdapter);
    }
}

Hier Layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.actviity.SplashDelayActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Hier mein CustomFragmentStateAdapter

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public class CustomFragmentStateAdapter extends FragmentStateAdapter {
    private List<Fragment> listFragment = new ArrayList<>();

    public CustomFragmentStateAdapter(FragmentActivity fa, List<Fragment> list) {
        super(fa);
        listFragment = list;
    }

    @NotNull
    @Override
    public Fragment createFragment(int position) {
        return listFragment.get(position);
    }

    @Override
    public int getItemCount() {
        return 2;
    }
}

Und hier meine Fragmente:

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.myproject.android.R;

public class BluetoothPageFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.bluetooth_page_fragment, container, false);
    }

}

und zweites Fragment:

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.myproject.android.R;

public class QrPageFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.qr_page_fragment, container, false);
    }

}

Und als Ergebnis verwende ich jetzt androidx.viewpager2.widget.ViewPager2mit meinen benutzerdefinierten Fragmenten.

Und es ist Arbeit !!!

Nett.

PS Ein weiteres Gerät:

public class CustomFragmentStateAdapter extends FragmentStateAdapter {
    private ArrayList<Fragment> arrayList = new ArrayList<>();

    public CustomFragmentStateAdapter (FragmentActivity fa) {
        super(fa);
    }

    public void addFragment(Fragment fragment) {
        arrayList.add(fragment);
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        // return your fragment that corresponds to this 'position'
        return arrayList.get(position);
    }
}

Und verwenden Sie wie folgt (in Aktivität):

 myViewPager2 = findViewById(R.id.viewPager2);
        myAdapter = new CustomFragmentStateAdapter (this);
        myAdapter.addFragment(new QrPageFragment());
        myAdapter.addFragment(new BluetoothPageFragment());
        myViewPager2.setAdapter(myAdapter);

Ich habe es verwendet, mit einem Rückblick auf Bilder in FragmentPageAdapter und es ist zu langsam wie ein Schwein, das mit Pferden läuft.
Gilberto Ibarra

3
Das ist nicht richtig. createFragmentRückruf des FragmentStateAdapterSolls (wie die Methode sagt) createa Fragment. Und nicht eine geben, die bereits erstellt wurde und herumliegt. Wenn Sie Ihren Ansatz verwenden, bringen Sie die FragmentManager'sBedienung durcheinander .
Bartek Lipinski

@BartekLipinski. Also, wie ich "die Fragmentsammlung zur Laufzeit dynamisch ändern kann und ViewPager2 die geänderte Sammlung korrekt anzeigt." wie die Dokumentation sagt?
Ramaral

0

Wie man es benutzt, wird sehr klar erklärt. Lassen Sie mich kleine, aber sehr wichtige Tipps und Details zu ViewPager2 geben, insbesondere wenn es sich in einem Fragment befindet, wie Speicherlecks verhindert werden können

  1. Verwenden Sie nicht den Konstruktor, der Fragmente nimmt, insbesondere wenn Sie verwenden TabLayout.

    public FragmentStateAdapter(@NonNull Fragment fragment) {
        this(fragment.getChildFragmentManager(), fragment.getLifecycle());
    }
    

weil das Risiko eines Speicherverlusts besteht, wie hier beschrieben

Verwenden Sie stattdessen FragmentManager und LifeCycle. Und senden Sie kein lifeCycleFragment als Argument, verwenden Sie viewLifeCycleOwnerden Lebenszyklus, da viewLifeCycleOwner den Lebenszyklus von Fragmenten darstellt view.

 class NavigableFragmentStateAdapter(
    fragmentManager: FragmentManager,
    lifecycle: Lifecycle
) : FragmentStateAdapter(fragmentManager, lifecycle) {


}

und Adapter mit in einstellen onCreateView

viewPager.adapter =
            NavigableFragmentStateAdapter(childFragmentManager, viewLifecycleOwner.lifecycle)
  1. Wenn Sie verwenden, TabLayoutwenn sich ViewPager2 in einem Fragment befindet, vergessen Sie nicht, TabLayout zu trennen und den Adapter von ViewPager2 als festzulegen

Trennen Sie TabLayoutMediator, da es Speicherlecks verursacht, wenn es sich in einem Fragment befindet

/programming/61779776/leak-canary-detects-memory-leaks-for-tablayout-with-viewpager2

ViewPager2 in einem Fragment leckt, nachdem das Fragment, in dem es sich befindet, durch die Navigation der Navigationskomponente ersetzt wurde

TabLayoutMediator(tabLayout, viewPager2, tabConfigurationStrategy).detach()     
viewPager2.adapter = null

innere onDestroyViewMethode des Fragments

  1. Wenn Sie Seiten von ViewPager wie navHostFragmentNavigationskomponenten verwenden möchten, um zu untergeordneten Fragmenten zurückzukehren, registrieren Sie FragmentTransactionCallback in FragmentStateAdapteras

    private val fragmentTransactionCallback =
        object : FragmentStateAdapter.FragmentTransactionCallback() {
            override fun onFragmentMaxLifecyclePreUpdated(
                fragment: Fragment,
                maxLifecycleState: Lifecycle.State
            ) = if (maxLifecycleState == Lifecycle.State.RESUMED) {
    
                // This fragment is becoming the active Fragment - set it to
                // the primary navigation fragment in the OnPostEventListener
                OnPostEventListener {
                    fragment.parentFragmentManager.commitNow {
                        setPrimaryNavigationFragment(fragment)
                    }
                }
            } else {
                super.onFragmentMaxLifecyclePreUpdated(fragment, maxLifecycleState)
            }
        }
    
    init {
        // Add a FragmentTransactionCallback to handle changing
        // the primary navigation fragment
        registerFragmentTransactionCallback(fragmentTransactionCallback)
    }
    

Wenn Sie einige Beispiele zur Verwendung von ViewPager2 mit Navigationskomponenten, dynamischen Funktionsmodulen und zur Kombination mit BottomNavigationView sehen möchten, können Sie die Tutorials in diesem Github-Repo lesen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.