I have the Figma model, but can't do right, in all cases that I've tried, I've got too wide tab indicator or too compressed. I think, maybe exist some solution to add extra space between tabs. I can`t add the image to this post, i put link on my google photo. You will see 2 photo, left photo - What i need
https://photos.app.goo.gl/CiwR7DemvCcQxWFz6
XML for
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".activity.QuizActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="90dp"
android:background="#color/colorBolotoButton"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
<TextView
android:id="#+id/textViewToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_marginRight="120dp"
android:fontFamily="#font/bellota_bold"
android:gravity="center_vertical"
android:text="Проверим знания!"
android:textColor="#color/cardview_light_background"
android:textSize="24dp" />
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.tabs.TabLayout
android:layout_marginTop="16dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_width="wrap_content"
android:id="#+id/tabLayout"
app:tabGravity="center"
android:layout_gravity="center_horizontal"
app:tabIndicatorGravity="center"
app:tabMode="fixed"
app:tabIndicator="#drawable/circle"
app:tabIndicatorColor="#color/colorBolotoButton"
app:tabIndicatorHeight="32dp"
android:clipToPadding="true"
app:tabSelectedTextColor="#color/colorWhite"
android:clickable="false" >
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/quizViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp" />
</LinearLayout>
Adapter
class QuizAdapter(activity: AppCompatActivity, val itemsCount: Int)
: FragmentStateAdapter(activity) {
override fun getItemCount(): Int {
return itemsCount
}
override fun createFragment(position: Int): Fragment {
return QuizFragment.getinstance(position)
}
}
Activity
class QuizActivity : AppCompatActivity() {
private var testArray = arrayListOf("1", "2", "3", "4", "5", "6", "7", "8")
// private var QuizPageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
// override fun onPageSelected(position: Int) {
// Toast.makeText(this#QuizActivity, "Selected position: ${position}",
// Toast.LENGTH_SHORT).show()
// }
// }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
val viewPager: ViewPager2 = findViewById(R.id.quizViewPager)
val pagerAdapter = QuizAdapter(this, testArray.size)
viewPager.adapter = pagerAdapter
/*
Method for concatenation ViewPager and tabLayout
*/
TabLayoutMediator(tabLayout, quizViewPager) { tab, position ->
tab.text=testArray[position]
}.attach()
Fragment
class QuizFragment : Fragment() {
companion object {
const val ARG_PAGE = "ARG_PAGE"
// Method for creating new instances of the fragment
fun getinstance(page: Int): QuizFragment {
val fragment = QuizFragment()
val args = Bundle()
args.putInt(ARG_PAGE, page)
fragment.arguments = args
return fragment
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val position = requireArguments().getInt(ARG_PAGE) + 1
textViewFragment.text = "Fragment #$position"
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val viewfragment = inflater.inflate(R.layout.fragment_page, container, false)
var position = requireArguments().getInt(ARG_PAGE)
val textView = viewfragment.findViewById<TextView>(R.id.textViewFragment)
textView.setText("Fragment #${++position}")
return viewfragment
}
}
Related
The following problem occurred with me after migration from viewPager to viewPager2 - when I open my app, the tablyout indicator is missing by default. But if you make some swiping, the indicator will appears! Looks weird, because I made everything correct. There are my simplified Kotlin-code:
class ScheduleWeekFragment : ScheduleBaseFragment<ScheduleWeekViewModel>(ScheduleWeekViewModel::class) {
private val viewBinding by viewBinding(FragmentWeekBinding::bind)
private var titles: Array<String>? = null
// listeners
private val viewPagerListener = object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
viewModel.updateDayTitle(position)
}
}
// observers
private val selectedDayObserver = Observer<Int> {
viewBinding.viewPager2.currentItem = it
}
// lifecycle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
titles = context?.resources?.getStringArray(R.array.schedule_fragment_day_abbreviations)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.fragment_week, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewBinding.viewPager2.adapter = ScheduleViewPagerAdapter(this)
viewBinding.viewPager2.setPageTransformer(ZoomOutPageTransformer)
TabLayoutMediator(viewBinding.tabLayout, viewBinding.viewPager2) { tab, position ->
tab.text = titles?.getOrNull(position)
}.attach()
// observers
viewModel.viewPagerPosition.observe(viewLifecycleOwner, selectedDayObserver)
// listeners
viewBinding.viewPager2.registerOnPageChangeCallback(viewPagerListener)
}
override fun onDestroyView() {
viewBinding.viewPager2.unregisterOnPageChangeCallback(viewPagerListener)
super.onDestroyView()
}
}
And there is my simplified xml-code:
<?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:id="#+id/fragmentWeek"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
style="#style/TabLayout1"
android:layout_width="match_parent"
android:layout_height="40dp"
android:verticalScrollbarPosition="left"
app:layout_constraintEnd_toEndOf="#+id/viewPager2"
app:layout_constraintStart_toStartOf="#+id/viewPager2"
app:layout_constraintTop_toBottomOf="#+id/scheduleToolbar"
app:tabGravity="start"
app:tabMode="scrollable"
android:background="#color/white"
tools:ignore="SpeakableTextPresentCheck" />
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPager2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tabLayout"
tools:ignore="SpeakableTextPresentCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>
The problem was inside my observer:
private val selectedDayObserver = Observer<Int> {
// viewBinding.viewPager2.currentItem = it // wrong!
viewBinding.viewPager2.setCurrentItem(it, false) // correct!
}
I didn't find why in the official docs, but difference exists: the first variant works good with viewpager1, but for viewpager2, be careful and use the second complex variant.
I have one AlertSettingfragment which has two tabItem ( SMS text and Email). I have created two fragments for viewpager(SMStext Fragment and Email Fragment) according to the tabItem. But i am not able to connect to the viewpager. Please Help
fragment_alertSetting.xml
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="42dp"
android:layout_margin="2dp"
android:backgroundTint="#color/gray"
app:tabBackground="#drawable/track_selector"
app:tabGravity="fill"
app:tabIndicatorHeight="0dp"
app:tabMode="fixed"
app:tabRippleColor="#color/transparent"
app:tabSelectedTextColor="#color/dark_blue"
app:tabTextAppearance="#style/CustomTextAppearanceTab"
app:tabTextColor="#color/gray_blue">
<com.google.android.material.tabs.TabItem
android:id="#+id/smsTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sms_text" />
<com.google.android.material.tabs.TabItem
android:id="#+id/emailTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/email" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/alertSettingViewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginHorizontal="12dp"
android:layout_marginVertical="16dp"
android:background="#color/white"
app:layout_constraintTop_toBottomOf="#id/tabLayoutView" />
AlertSettingFragment.kt
#AndroidEntryPoint
class CascadeSettingsAlertFragment : Fragment() {
private lateinit var binding: FragmentCascadeSettingsAlertBinding
private var listener: OnFragmentInteractionListener? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentCascadeSettingsAlertBinding.inflate(inflater,container,false).apply {
alertSettingViewPager.adapter = CascadeAlertSettingAdapter(this#CascadeSettingsAlertFragment)
TabLayoutMediator(
tabLayout,
alertSettingViewPager
) { tabs, position ->
val tabBinding = when (position) {
SMS_PAGE_INDEX -> binding.smsTab
EMAIL_PAGE_INDEX -> binding.emailTab
else -> binding.smsTab
}
tabs.view = tabBinding.
}.attach()
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
AlertSettingAdapter.kt
const val SMS_PAGE_INDEX = 0
const val EMAIL_PAGE_INDEX = 1
class CascadeAlertSettingAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
private val tabFragmentsCreators: Map<Int, () -> Fragment> = mapOf(
SMS_PAGE_INDEX to { AlertSettingsSmsFragment() },
EMAIL_PAGE_INDEX to { AlertSettingsEmailFragment() },
)
override fun getItemCount() = tabFragmentsCreators.size
override fun createFragment(position: Int): Fragment {
return tabFragmentsCreators[position]?.invoke() ?: throw IndexOutOfBoundsException()
}
}
You have to add the TabItems programmatically to the TabLayout, TabItems added via XML are not actually added to the TabLayout, as mentioned in the documentation of TabLayout.
More info:
https://developer.android.com/reference/com/google/android/material/tabs/TabItem
I found an interesting feature in one of the applications, I want to repeat it. The application has ViewPager and TabLayout and a bunch of fragments inside.
On the first fragment there is a button img1
, by pressing it, the fragment is replaced by another img2
while ads_banner is removed and the toolbar is replaced,
and when swiping to the right and back, it shows fragment1, please tell me how this can be done. Here is what I already wrote:
MainActivity
class MainActivity : AppCompatActivity() {
private var mAdView: AdView? = null
#SuppressLint("ResourceType")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adRequest = AdRequest.Builder().build()
mAdView = findViewById(R.id.adView)
mAdView!!.loadAd(adRequest)
initTab()
}
fun initTab() {
tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image1)
tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image2)
tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image3)
tab_layout.tabGravity = TabLayout.GRAVITY_FILL
val adapter = MyPagerAdapter(supportFragmentManager, tab_layout.tabCount)
pager.adapter = adapter
pager.offscreenPageLimit = 2
pager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tab_layout))
tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
pager.currentItem = tab.position
if (tab.position == 0) {
tab_layout.getTabAt(0)!!.setIcon(R.drawable.image1_focus)
}
if (tab.position == 1) {
tab_layout.getTabAt(1)!!.setIcon(R.drawable.image2_focus)
}
if (tab.position == 2) {
tab_layout.getTabAt(2)!!.setIcon(R.drawable.image3_focus)
}
}
override fun onTabUnselected(tab: TabLayout.Tab) {
if (tab.position == 0) tab_layout.getTabAt(0)!!.setIcon(R.drawable.image1)
if (tab.position == 1) tab_layout.getTabAt(1)!!.setIcon(R.drawable.image2)
if (tab.position == 2) tab_layout.getTabAt(2)!!.setIcon(R.drawable.image3)
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})
}
activity_main.xml
<?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:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context=".MainActivity">
<com.google.android.gms.ads.AdView
android:id="#+id/adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="#color/transparent"
app:adSize="SMART_BANNER"
app:adUnitId="#string/banner_key"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
style="#style/MyToolbar"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginTop="2dp"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/adView"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="#font/sf_pro_display_regular"
android:textColor="#color/black"
android:textSize="24sp"
tools:layout_editor_absoluteX="206dp"
tools:layout_editor_absoluteY="7dp" />
</androidx.appcompat.widget.Toolbar>
<androidx.viewpager.widget.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/tab_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbar" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#fff"
android:elevation="6dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tabBackground="#drawable/tab_color_selector"
app:tabIndicatorColor="#2196F3"
app:tabIndicatorGravity="top"
app:tabIndicatorHeight="4dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
MyPagerAdapter
class MyPagerAdapter(fm: FragmentManager, internal var mNumOfTabs: Int) : FragmentStatePagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
when (position) {
0 -> {
return RootFragment()
// return Fragment1()
}
1 -> {
return Fragment2()
}
2 -> {
return Fragment3()
}
}
}
override fun getCount(): Int {
return mNumOfTabs
}
}
Fragment1
class Fragment1: Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_1, container, false)
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
btnfr1.setOnClickListener {
val trans = fragmentManager!!.beginTransaction()
trans.replace(R.id.root_frame, Fragment4())
trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
trans.addToBackStack(null)
trans.commit()
}
}
RootFragment
class RootFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.root_fragment, container, false)
val transaction = fragmentManager!!.beginTransaction()
transaction.replace(R.id.root_frame, Fragment1())
transaction.commit()
return view
}
}
root_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root_frame" >
</FrameLayout>
In Fragment1, only the button for calling Fragment4. Tried to do as here https://www.codexpedia.com/android/android-viewpager-fragment-swap/
it turned out to replace Fragment1 with Fragment4, but I don’t know how to reset Fragment4 when swiping and don’t understand how to replace Toolbar and remove ads.
The trick is that as RootFragment is the fragment on the 0th index, what you need to do is show the original fragment as a child fragment of RootFragment using fragment transactions via childFragmentManager.
This way, you can replace the children of RootFragment, without actually having to replace RootFragment itself inside the ViewPager.
You need to implement createFragment and getItemCount methods in MyPagerAdapter to supply instances of fragments as pages to ViewPager.
Modify MyPagerAdapter class as shown below and test:
class MyPagerAdapter(fm: FragmentManager, internal var mNumOfTabs: Int) : FragmentStatePagerAdapter(fm) {
override fun getItemCount(): Int = mNumOfTabs
override fun createFragment(position: Int): Fragment {
when (position) {
0 -> {
return RootFragment()
}
1 -> {
return Fragment2()
}
2 -> {
return Fragment3()
}
}
}
}
I have implemented BottomSheetDialogFragment into OptionsFragment.In which I have added viewpager so I can do swipe animation for SignInSignUpOptionsFragment which I want to add in viewpager and button to Swipe SignInSignUpOptionsFragment with different option. SignInSignUpOptionsFragment has options of Login(+ social accounts).
AccountFragment
login_btn.onClickListener( v -> {
OptionsFragment optionsFragment = new OptionsFragment(true);
optionsFragment.show(getChildFragmentManager(), "Login");
});
OptionsFragment
class OptionsFragment(private val isLogin: Boolean) : BottomSheetDialogFragment() {
private var fragmentView: View? = null
lateinit var viewPager: ViewPager
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
fragmentView = inflater.inflate(R.layout.signup_popover, container, false)
val pagerAdapter = MyPagerAdapter(childFragmentManager)
viewPager = fragmentView!!.findViewById(R.id.vpPager)
viewPager.adapter = pagerAdapter
viewPager.currentItem = 0
return fragmentView
}
}
class MyPagerAdapter(fragmentManager: FragmentManager?) : FragmentStatePagerAdapter(fragmentManager!!, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
// Returns total number of pages
override fun getCount(): Int {
return NUM_ITEMS
}
// Returns the fragment to display for that page
override fun getItem(position: Int): Fragment {
return when(position) {
0 -> SignInSignUpOptionsFragment.newInstance(true)
1 -> SignInSignUpOptionsFragment.newInstance(false)
else -> null!!
}
}
// Returns the page title for the top indicator
override fun getPageTitle(position: Int): CharSequence? {
return "Page $position"
}
companion object {
private const val NUM_ITEMS = 2
}
here's my layout file
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/utilityGrey2">
<androidx.viewpager.widget.ViewPager
android:id="#+id/vpPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent" />
<LinearLayout
android:id="#+id/login_no_account_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:layout_marginLeft="21dp"
android:layout_marginRight="21dp"
android:layout_marginTop="52dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/vpPager">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/switch_sign_up_description"
style="#style/HelpText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/no_account" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/switch_sign_up"
style="#style/HelpText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/sign_up_caps" />
</LinearLayout>
but I am not able to see any fragment inside ViewPager. Only bottom "login_no_account_group" is displaying as Bottomsheet. I don't want to use TabLayout, instead I want to change page on switch_sign_up click
viewPager.currentItem = 1
Is it possible ? any other alternative welcome as well
I am trying to implement RecyclerViewPagerIndicator in my project, but I can't get it to work.
I work with Kotlin and AndroidX
I expect send a array with text and images from database and show in RecyclerViewPager, something like tinder.
I would suggest you to use dotsIndicator, since it
supports ViewPager 2 which is based on RecyclerView
is maintained, one you picked is not (project seems abandoned)
is written in Kotlin
Example:
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"
android:gravity="center"
tools:context=".MainActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager_2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<com.tbuonomo.viewpagerdotsindicator.WormDotsIndicator
android:id="#+id/dots_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"/>
</LinearLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupViewPager2()
}
private fun setupViewPager2() {
val viewPager2 = findViewById<ViewPager2>(R.id.view_pager_2)
val dotsIndicator = findViewById<WormDotsIndicator>(R.id.dots_indicator)
viewPager2.adapter = PagerAdapter(this)
dotsIndicator.setViewPager2(viewPager2)
}
}
PagerAdapter.kt
class PagerAdapter(fa:FragmentActivity): FragmentStateAdapter(fa) {
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment {
return when(position){
0 -> SampleFragment.newInstance("One", "desc 1")
1 -> SampleFragment.newInstance("Two", "desc 2")
2 -> SampleFragment.newInstance("Three", "desc 3")
else -> throw Exception("No such position")
}
}
}
fragment_sample.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"
android:gravity="center"
tools:context=".SampleFragment">
<TextView
android:id="#+id/txt_header"
tools:text="Header 1"
android:textAlignment="center"
android:textSize="24sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/txt_desc"
tools:text="Desc 1"
android:textAlignment="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
SampleFragment.kt
class SampleFragment : Fragment() {
private var header: String? = null
private var desc: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
header = it.getString(ARG_Header)
desc = it.getString(ARG_Desc)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_sample, container, false)
setView(view)
return view
}
private fun setView(view:View){
val headerText = view.findViewById<TextView>(R.id.txt_header)
headerText.text = header
val descText = view.findViewById<TextView>(R.id.txt_desc)
descText.text = desc
}
companion object {
#JvmStatic
fun newInstance(param1: String, param2: String) =
SampleFragment().apply {
arguments = Bundle().apply {
putString(ARG_Header, param1)
putString(ARG_Desc, param2)
}
}
}
}