Я дізнався про ViewPager2 і спробував його реалізувати, але не знайшов жодного належного прикладу.
Хто-небудь може сказати мені, як я можу ним користуватися.
Я шукаю правильного використання, а не прикладу.
Я дізнався про ViewPager2 і спробував його реалізувати, але не знайшов жодного належного прикладу.
Хто-небудь може сказати мені, як я можу ним користуватися.
Я шукаю правильного використання, а не прикладу.
recommend or find a book, tool, software library, tutorial or other off-site resource
будь ласка, уважно прочитайте, що я не шукаю приклад.
Відповіді:
Перевірка: Мігруйте з ViewPager на ViewPager2
Позначка : Створіть подання пальцем за допомогою вкладок за допомогою ViewPager2
Перевірте мою відповідь, якщо ви хочете застосувати Карусель за допомогою View Pager2
Як використовувати TabLayout з ViewPager2
ЗРАЗОК КОДУ
Використовуйте нижче dependencies
implementation 'com.google.android.material:material:1.1.0-alpha08'
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
ЗРАЗОК КОДУ
Розмітка XMl
<?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>
Діяльність
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()
}
}
ВИХІД
З Документів
Нові можливості
Зміни API
FragmentStateAdapter
замінює FragmentStatePagerAdapter
RecyclerView.Adapter
замінює PagerAdapter
registerOnPageChangeCallback
замінює addPageChangeListener
ЗРАЗОК КОДУ
додати останню версію
dependencies
дляViewPager2
implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha01'
макет
<?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>
діяльність
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);
}
}
}
тепер нам потрібно використовувати,
ViewPager2.OnPageChangeCallback()
щоб отримати Swipe подіюViewPager2
ЗРАЗОК КОДУ
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);
}
});
ми можемо встановити Орієнтацію за допомогою
myViewPager2.setOrientation()
ЗРАЗОК КОДУ
Для HORIZONTAL Orientation
використання
myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
Для VERTICAL Orientation
використання
myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
Ми можемо використовувати те
notifyDataSetChanged
саме, що і вRecyclerView.Adapter
ЗРАЗОК КОДУ, щоб додати новий елемент
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
arrayList.add("New ITEM ADDED");
MyAdapter.notifyDataSetChanged();
}
});
ЗРАЗОК КОДУ, щоб видалити новий елемент
btnRemove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
arrayList.remove(3);
MyAdapter.notifyItemRemoved(3);
}
});
Fragment
зViewPager2
Спочатку створіть
ViewPagerFragmentAdapter
клас, який розширюєтьсяFragmentStateAdapter
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();
}
}
Тепер використовуйте так у своїй діяльності
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);
}
}
для отримання додаткової інформації перевірте це
Нові можливості
setUserInputEnabled
, isUserInputEnabled
)Зміни API
ViewPager2
фінал класуВиправлення помилок
FragmentStateAdapter
виправлення стабільностіЗРАЗОК КОДУ, щоб вимкнути проведення пальцем у viewpager2
myViewPager2.setUserInputEnabled(false);// SAMPLE CODE to disable swiping in viewpager2
myViewPager2.setUserInputEnabled(true);//SAMPLE CODE to enable swiping in viewpager2
Нові можливості
Зміни API
FragmentStateAdapter
тепер потрібен Lifecycle
об’єкт. Додано два конструктори утиліти, щоб отримати його від хоста FragmentActivity
або фрагмента хостуЗРАЗОК КОДУ
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
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);
}
}
Version 1.0.0-alpha05
Нові можливості
ItemDecorator
введено з поведінкою, що відповідає RecyclerView
.MarginPageTransformer
представлений, щоб забезпечити можливість створювати простір між сторінками (поза вставкою сторінки).CompositePageTransformer
представлений для забезпечення можливості поєднання кількох PageTransformers
Зміни API
FragmentStateAdapter#getItem
метод, перейменований на FragmentStateAdapter#createFragment
- попередня назва методу в минулому виявилась джерелом помилок.OFFSCREEN_PAGE_LIMIT_DEFAULT
значення змінено з 0 на -1. Не потрібно змінювати код клієнта, якщо він OFFSCREEN_PAGE_LIMIT_DEFAULTconstant
використовується.ЗРАЗОК КОДУ
Код діяльності
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;
}
}
PagerTitleStrip
або PagerTabStrip
з ViewPager2, або, можливо, є альтернатива?
Насправді зараз існує офіційний зразок репозиторію для ViewPager2 (посилання нижче)
РЕПО містить наступні зразки (цитування з репо-репозиторію нижче)
Зразки
- ViewPager2 з поданнями - показує, як налаштувати ViewPager2 з поданнями як сторінки
- ViewPager2 з фрагментами - показує, як налаштувати ViewPager2 з фрагментами як сторінками
- ViewPager2 з змінною колекцією (Views) - демонструє використання ViewPager2 з поданнями як сторінки та мутації в адаптері сторінок
- ViewPager2 з мінливою колекцією (фрагменти) - демонструє використання ViewPager2 з фрагментами як сторінками та мутаціями в адаптері сторінок
- ViewPager2 з TabLayout (Views) - показує, як налаштувати ViewPager2 з поданнями як сторінками та зв’язати його з TabLayout
Простий приклад ViewPager2 з фрагментами в 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.kt
і ThirdFragment.kt
схожий на 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]
}
Деякі інші корисні ресурси:
Навчання: https://developer.android.com/training/animation/screen-slide-2
Примітки до випуску: https://developer.android.com/jetpack/androidx/releases/viewpager2
Середня стаття GDE: Дослідження ViewPager2
Використання ViewPager2 в Android
Як згадувалося на сайті розробника
Зміни API
FragmentStateAdapter замінює FragmentStatePagerAdapter
RecyclerView.Adapter замінює PagerAdapter
registerOnPageChangeCallback замінює addPageChangeListener
Простими словами вони роблять так, щоб адаптер View Pager працював як адаптер Recycle View.
Примітка: - Нам не потрібно використовувати фрагмент у View Pager 2. Це повністю залежить від макета надуття RecyclerView.Adapter.
Ось зразок посилання на репозитарій gitHub
Приклад: -
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);
}
}
вихід:
Fragment
з, ViewPager2
будь ласка, перевірте мою відповідь вище, я додав зразок коду для How use Fragment with ViewPager2
Ось що я зробив для реалізації ViewPager2 з TabLayout з 3 Fragment full Examble:
Макет містить ViewPager2
з 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>
init ViewPager2 та встановіть ім'я Tabs:
@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
адаптер:
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;
}
залежність, що використовується:
implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation 'com.google.android.material:material:1.1.0-alpha10'
Ось моє рішення (Android Studio 3.6):
У 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"
}
Ось моя діяльність:
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);
}
}
Ось макет:
<?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>
Тут мій 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;
}
}
І ось мої фрагменти:
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);
}
}
і другий фрагмент:
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);
}
}
І як результат зараз я використовую androidx.viewpager2.widget.ViewPager2
зі своїми користувацькими фрагментами.
І це робота !!!
Приємно.
PS Ще одна реалізація:
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);
}
}
І використовуйте так (в діяльності):
myViewPager2 = findViewById(R.id.viewPager2);
myAdapter = new CustomFragmentStateAdapter (this);
myAdapter.addFragment(new QrPageFragment());
myAdapter.addFragment(new BluetoothPageFragment());
myViewPager2.setAdapter(myAdapter);
createFragment
зворотний виклик FragmentStateAdapter
слід (як говорить метод) create
a Fragment
. І не дайте тієї, яка вже створена і валяється. Використовуючи свій підхід, ви заплутуєтесь з FragmentManager's
операцією.
Як це використовувати, дуже чітко пояснено. Дозвольте мені дати невеликі, але дуже важливі поради та подробиці щодо ViewPager2, особливо якщо це всередині фрагмента про те, як запобігти витоку пам'яті
Не використовуйте конструктор, який бере фрагмент, особливо якщо ви використовуєте TabLayout
.
public FragmentStateAdapter(@NonNull Fragment fragment) {
this(fragment.getChildFragmentManager(), fragment.getLifecycle());
}
оскільки існує ризик витоку пам’яті, як описано тут
замість цього використовуйте один, який бере FragmentManager та LifeCycle. І не надсилайте lifeCycle
фрагмент як аргумент, використовуйте viewLifeCycleOwner
життєвий цикл ', оскільки viewLifeCycleOwner представляє життєвий цикл фрагмента view
.
class NavigableFragmentStateAdapter(
fragmentManager: FragmentManager,
lifecycle: Lifecycle
) : FragmentStateAdapter(fragmentManager, lifecycle) {
}
і встановити адаптер з в onCreateView
viewPager.adapter =
NavigableFragmentStateAdapter(childFragmentManager, viewLifecycleOwner.lifecycle)
TabLayout
коли ViewPager2 знаходиться всередині фрагмента, не забудьте від'єднати TabLayout та встановити адаптер ViewPager2 яквід'єднайте TabLayoutMediator, оскільки він спричиняє витік пам'яті, коли він знаходиться у фрагменті
/programming/61779776/leak-canary-detects-memory-leaks-for-tablayout-with-viewpager2
TabLayoutMediator(tabLayout, viewPager2, tabConfigurationStrategy).detach()
viewPager2.adapter = null
внутрішній onDestroyView
метод Fragment
Якщо ви хочете використовувати сторінки ViewPager як navHostFragment
із навігаційними компонентами, щоб повернутися до дочірніх фрагментів, зареєструйте FragmentTransactionCallback в FragmentStateAdapter
як
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)
}
Крім того, якщо ви хочете побачити деякі зразки використання ViewPager2 з навігаційними компонентами, модулями динамічних функцій та поєднанням з BottomNavigationView, ви можете ознайомитись з підручниками в цьому репозиторії github.
Спочатку я створив пейджер перегляду, а потім перейшов на перегляд пейджера 2, використовуючи інструкції, наведені в: https://developer.android.com/training/animation/vp2-migration