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
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()
}
}
}
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
}
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).
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
}
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.