Reverse swiping direction in ViewPager - android

is there any possible way to change the swiping of a fragments from left to right?
my Fragments swipes from right to left but I need the fragments to swipe from left to right.
Pager Adapter.kt
class pageradapter (fm: FragmentManager) : FragmentStatePagerAdapter(fm){
override fun getItem(position: Int): Fragment {
when(position){
0-> return fragment1()
1-> return fragment2()
else-> return fragment3()
}
}
override fun getCount(): Int {
return 3
}
fragment1.kt // 2 and 3 has the same code
class fragment1 : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment1, container, false)
}
Main4Activity.kt
class Main4Activity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main4)
val adapter = pageradapter(supportFragmentManager)
val pager = findViewById<View>(R.id.pager) as ViewPager
pager.adapter = adapter
}

You should reverse the Fragment positions like following:
In PagerAdapter.kt
class pageradapter (fm: FragmentManager) : FragmentStatePagerAdapter(fm){
override fun getItem(position: Int): Fragment {
when(rotatePosition(position)) {
0-> return fragment1()
1-> return fragment2()
else-> return fragment3()
}
}
override fun getCount(): Int {
return 3
}
private fun rotatePosition(position: Int): Int {
return (getCount() - 1) - position
}
}
In Main4Activity:
class Main4Activity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main4)
val adapter = pageradapter(supportFragmentManager)
val pager = findViewById<View>(R.id.pager) as ViewPager
pager.adapter = adapter
// setting new start position
pager.setCurrentItem(adapter.rotatePosition(0), false);
}

You can animate it using a PageTransformer
Or,
if you want the animation on replacing a fragment, you can set a custom animation on the FragmentTransaction

Related

Responding to ViewPager2 Fragments Events in Activity

I have a main activity that contains a ViewPager2 and a TabLayout to house a few fragments. Each fragment will have buttons that I want to trigger actions in the main activity. However, I'm not seeing how to set up the buttons/event handlers so that the main activity is notified whenever a button is pressed inside one of the fragments. Thanks!
MenuActivity.kt - ViewPager2/TabLayout Setup
private fun configureMenu() {
// Create adapter
val fragmentAdapter = PageAdapter(supportFragmentManager, lifecycle)
// Add fragments
fragmentAdapter.addFragment(CameraFragment(), getString(R.string.camera_tab))
fragmentAdapter.addFragment(DevicesFragment(), getString(R.string.devices_tab))
fragmentAdapter.addFragment(ConnectionFragment(), getString(R.string.connection_tab))
// Set up pageviewer
viewpager_menu.adapter = fragmentAdapter
TabLayoutMediator(tablayout_main, viewpager_menu) { tab, position ->
tab.text = fragmentAdapter.getPageTitle(position)
viewpager_menu.setCurrentItem(tab.position, true)
}.attach()
}
PageAdapter.kt
class PageAdapter(fm: FragmentManager, lifecycle: Lifecycle): FragmentStateAdapter(fm, lifecycle) {
private var fragmentList = ArrayList<Fragment>()
private var fragmentTitleList = ArrayList<String>()
fun addFragment(fragment: Fragment, title: String) {
fragmentList.add(fragment)
fragmentTitleList.add(title)
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
}
override fun getItemCount(): Int {
return fragmentList.size
}
override fun createFragment(position: Int): Fragment {
return fragmentList[position]
}
fun getPageTitle(position: Int): String {
return fragmentTitleList[position]
}
}
CameraFragment.kt
class CameraFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_camera, container, false)
}
}
Thanks!
Inside actions of the fragment
val main = this.activity!! as MainActivity
main.callSomeFunc()
You can pass the this object of activity in specific frament constructor and use from fragment to call the activity class method
for example:
class MenuActivity : AppCompatActivity(){
fragmentAdapter.addFragment(CameraFragment(this), getString(R.string.camera_tab))
}
class CameraFragment : Fragment {
var mActivity: MenuActivity? = null
constructor(mActivity: MenuActivity?) {
this.mActivity = mActivity
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_camera, container, false)
onlick{
mActivity.callMethodOfMenuActivity()
}
}
}

How to add a viewPager for swiping between fragments without adding an activity

I am developing a Kotlin app and at some point I want to implement viewPager to swipe between fragments. I have one activity to navigate to the rest of the app through the navigation graph. I have not really understood how this swiping should work.
My question is, do I need to implement a new activity as well besides the pageAdapter? And how this activity is going to cooperate with the main one? My app currently has a splash screen, and after that I would like to have the swipe mode between the fragments.
I want to implement viewPager to swipe between fragments.
nice
I have one activity to navigate to the rest of the app through the navigation graph.
cool
do I need to implement a new activity as well besides the pageAdapter?
no
And how this activity is going to cooperate with the main one?
don't have a second activity, then it doesn't need to "cooperate"
I would like to have the swipe mode between the fragments.
https://gist.github.com/Zhuinden/c643f03a023a9cbe83fff6c75c948d3b
class MyFragmentPagerAdapter(
private val context: Context,
fragmentManager: FragmentManager
) : FragmentPagerAdapter(fragmentManager) {
override fun getCount() = 2
override fun getItem(position: Int) = when(position) {
0 -> FirstFragment()
1 -> SecondFragment()
else -> throw IllegalStateException("Unexpected position $position")
}
override fun getPageTitle(position: Int): CharSequence = when(position) {
0 -> context.getString(R.string.first)
1 -> context.getString(R.string.second)
else -> throw IllegalStateException("Unexpected position $position")
}
}
class ParentFragment: Fragment() {
override fun onCreateView(...) = ...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val viewPager = view.findViewById(R.id.view_pager)
viewPager.adapter = MyFragmentPagerAdapter(requireContext(), childFragmentManager)
tabLayout.setupWithViewPager(viewPager)
}
}
Try this
in your viewPager
class pageradapter (fm: FragmentManager) : FragmentStatePagerAdapter(fm){
override fun getItem(position: Int): Fragment {
when(position){
0-> return fragment1()
1-> return fragment2() // you can add more if you have more fragments
else-> return fragment3()
}
}
override fun getCount(): Int {
return 3
number of fragments that you have so the swiping could work
}
in your fragments 1 or 2 or 3 ...etc'
class fragment1 : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment1, container, false)
// write your codes
}
in your Activity after the splash screen
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main4)
val adapter = pageradapter(supportFragmentManager)
val pager = findViewById<View>(R.id.pager) as ViewPager
pager.adapter = adapter
}

How can I destroy the tablayout fragments at the back event?

I have implemented a tableyout within a fragment, the logic is simple, when I click on an item in a list it derives to a fragment (tableyout), the problem happens when I go back and select another item it shows me the tableyout but with blank views, reviewing a behavior the fragments of the tablayout are never destroyed. Here is the adapter code and the main fragment. Thanks in advance.
class TabAdapter(fm: FragmentManager): FragmentPagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
return when(position){
0->FormPartOne()
1->FormPartTwo()
2->FormPartThree()
else->FormPartOne()
}
}
override fun getCount(): Int {
return 3
}
override fun getPageTitle(position: Int): CharSequence? {
return when(position){
0->"1"
1->"2"
2->"3"
else->""
}
}
}
Main Fragment:
class ReceptionFormFragment : Fragment() {
private lateinit var receptionOrderViewModel: ReceptionOrderViewModel
private lateinit var tabs: TabLayout
private lateinit var viewPager: ViewPager
private lateinit var sectionsPagerAdapter: TabAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_reception_form, container, false)
sectionsPagerAdapter = fragmentManager?.let { TabAdapter(it) }!!
viewPager = root.findViewById(R.id.view_pager)
viewPager.adapter = sectionsPagerAdapter
tabs = root.findViewById(R.id.tabs)
tabs.setupWithViewPager(viewPager)
return root
}
}
Replace
sectionsPagerAdapter = fragmentManager?.let { TabAdapter(it) }!!
With
sectionsPagerAdapter = TabAdapter(childFragmentManager)
And it will both work correctly and remove the fragments automatically on back (when this Fragment is removed).

Fragment's onCreateView doesn't get called when attached to viewpager

I'm trying to use a ViewPager that contains a fragment.
When I add a fragment using a FragmentPagerAdapter it doesn't work, and I noticed the 'onCreateView' function doesn't get called.
I tried following some tutorials but I can't seem to find the problem.
Here is the code:
class GuestListFragment : Fragment()
{
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
println("onCreateView")
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_guest_list, container, false)
}
}
class EventPagerAdapter(fragmentManager: FragmentManager): FragmentPagerAdapter(fragmentManager)
{
override fun getCount(): Int
{
return 0
}
override fun getItem(position: Int): Fragment
{
println("getItem")
return GuestListFragment()
}
}
class EventActivity : AppCompatActivity()
{
private lateinit var viewPager: ViewPager
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_event)
viewPager = findViewById(R.id.guests_view_pager)
val pagerAdapter = EventPagerAdapter(supportFragmentManager)
pagerAdapter.getItem(0)
viewPager.adapter = pagerAdapter
})
}
}
Change return count to 1 in getCount()
override fun getCount(): Int
{
return 1
}

Fragment inside a viewpager doesnt show when is in recyclerview

Maybe this is a stupid question, but this is ruining my day...
I have a recyclerview in a fragment
override fun setUpRecyclerView(pics: List<Pictures>) {
recyclerView.setHasFixedSize(true)
layoutManager = LinearLayoutManager(context)
recyclerView.setLayoutManager(layoutManager)
mAdapter = NewsAdapter(pics, childFragmentManager)
recyclerView.setAdapter(mAdapter)
}
the NewsAdapter is:
class NewsAdapter
(private val mDataset: List<Pictures>, private val fragmentManager: FragmentManager)
: RecyclerView.Adapter<NewsAdapter.ViewHolder>() {
class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
var authorTextView: TextView
var viewPager: ViewPager
var indicator: CircleIndicator
init {
authorTextView = v.findViewById<View>(R.id.tv_author) as TextView
viewPager = v.findViewById<View>(R.id.viewPager) as ViewPager
indicator = v.findViewById<View>(R.id.indicator) as CircleIndicator
}
}
override fun onCreateViewHolder(parent: ViewGroup,
viewType: Int): NewsAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.item_preview, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val pictureList = mDataset.get(position)
holder.titleTextView.text = pictureList.title
holder.authorTextView.text = pictureList.author
showContent(pictureList.content, holder.viewPager, holder.indicator)
}
fun showContent(contentModel: List<ContentModel>, viewPager: ViewPager, indicator: CircleIndicator) {
if (contentModel.size <= 1) {
indicator.hide()
}
viewPager.adapter = GalleryContentAdapter(fragmentManager, contentModel)
indicator.setViewPager(viewPager)
}
override fun getItemCount(): Int = mDataset.size
}
the GalleryContentAdapter is:
class GalleryContentAdapter(fm: FragmentManager, val contentModels: List<ContentModel>) : FragmentPagerAdapter(fm) {
val galleryContentFactory: GalleryContentFactory = GalleryContentFactory()
override fun getItem(position: Int): Fragment = galleryContentFactory.getFragment(contentModels[position])
override fun getCount(): Int = contentModels.size
}
From now I am only handling a kind of content and the factory is so easy, but this is the code:
class GalleryContentFactory {
fun getFragment(contentModel: ContentModel): Fragment {
when (contentModel.type) {
"PICTURE" -> return PictureFragment.newInstance(contentModel.value)
}
return PictureFragment.newInstance(contentModel.value)
}
}
and the last is the PictureFragment:
class PictureFragment : NewsContentFragment() {
companion object {
val KEY = "PictureFragment.URL"
fun newInstance(url: String): NewsContentFragment {
val fragment = PictureFragment()
val bundle = Bundle()
bundle.putString(KEY, url)
fragment.arguments = bundle
return fragment
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_news_gif, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
arguments?.getString(KEY).let {
view.image.loadUrl(it!!)
}
}
}
When I debug the code, I check that the line view.image.loadUrl(it!!) is being executed, but nothing is rendered.
The loadUrl method is a extended function of imageviews that loads an image using Glide like this
fun ImageView.loadUrl(url: String) {
GlideApp.with(context).load(url).into(this)
}
and is being called correctly.
I also tried with PagerStateAdapter and take into account that I am passing the ChildFragmentManager to the adapter of the ViewPager.
If you can help me, you will save my day. Thanks in advance
This doesn't work. The way to go is a recycler into a recycler. If you want simulate as a ViewPager, you may use https://github.com/rubensousa/RecyclerViewSnap with a MATCH_PARENT in the
child views.

Categories

Resources