Adding fragment to Android Developer Studio's Tabbed Activity Template - android-studio

Beginner here. Creating an app using the Android Developer Studios Tabbed Activity Template. I have two xml, the generated fragment_main.xml that comes with the template and secondtab.xml for what I want to be the second tab.
This is the code generated by the template:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
val viewPager: ViewPager = findViewById(R.id.view_pager)
viewPager.adapter = sectionsPagerAdapter
val tabs: TabLayout = findViewById(R.id.tabs)
tabs.setupWithViewPager(viewPager)
val fab: FloatingActionButton = findViewById(R.id.fab)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
I've been reading through the ViewPager documentation and a lot of what I can find is making this all from scratch and I'm having trouble understanding. I feel like I'm missing something obvious. How do I add my secondtab.xml to this pregenerated template so it shows up when the user clicks on the second tab?

Yours SectionsPagerAdapter getItem function should looks like this:
class SectionsPagerAdapter(
private val context: Context,
fm: FragmentManager
) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int) = when (position) {
0 -> FirstTabFragment()
1 -> SecondTabFragment()
else -> error("Unknown")
}
override fun getPageTitle(position: Int) = context.resources.getString(TAB_TITLES[position])
override fun getCount() = 2
}
Because by default in this template SectionsPagerAdapter always creates PlaceholderFragment:
override fun getItem(position: Int): Fragment {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1)
}
But in yours case you need use two different fragments with two different xml-layouts like this:
class FirstTabFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_main, container, false)
val textView: TextView = root.findViewById(R.id.section_label)
return root
}
}
class SecondTabFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.secondtab, container, false)
val textView: TextView = root.findViewById(R.id.section_label)
return root
}
}
Also make sure to add:
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginBottom="#dimen/activity_vertical_margin"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/constraintLayout"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1" />
to the fragment xml

Related

kotlin opening new Activity inside of a Fragment

Im getting an error on the second to last close brace.
Error: A 'return' expression required in a function with a block body ('{...}')
Im trying to open a Activity (TMs) from a ImageButton in my fragement (Dashboard).
class Dashboard : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_dashboard, container, false)
view.findViewById<ImageButton>(R.id.card1).setOnClickListener {
val card1 = Intent(activity, TMs::class.java)
activity?.startActivity(card1)
}
}
}
The function onCreateView does returns a View. You have inflated the View object, just return it.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view = inflater.inflate(R.layout.fragment_dashboard, container, false)
..code..
return view
Anyways, I do strongly recommend you to init the clickListeners and any other UI logic in onViewCreated().
So we proceed to create the fragment by steps, first we "inflate the view" which is on onCreateView(): View and then once it is created we can add UI logic (as listeners).
It would look like this:
class Dashboard : Fragment() {
private lateinit var _view: View
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_view = inflater.inflate(R.layout.fragment_dashboard, container, false)
return _view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
view.findViewById<ImageButton>(R.id.card1).setOnClickListener {
val card1 = Intent(activity, TMs::class.java)
activity?.startActivity(card1)
}
}
}

How do I pass the variables of an activity to the fragments of a BottomNavigationView?

I am very new to taking an android application and for a project I need a BottomNavigati but I cannot get my data that comes from the beginning of the session to pass to the main fragment
Activity:
val bundle1 = Bundle()
bundle1.putString("User",User)
bundle1.putString("Correo",Correo)
bundle1.putString("Region",Region)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController: NavController = navHostFragment.navController
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications
)
)
navHostFragment.arguments = bundle1
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
HOMEFRAGMEN:
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.textView4)
return root
}
}
There is no direct access to HomeFragment from MainActivity in your case. BottomNavigation uses nested navigation architecture pattern with nested graphs.
More details here: Passing argument(s) to a nested Navigation architecture component graph
But you can use alternative way to pass data from Activity to Fragment using context.
Step 1 - Describe HomeFragmentData model:
data class HomeFragmentData(
val value: String
)
Step 2 - Describe HomeFragment interface:
interface IHomeFragment {
fun getHomeFragmentData(): HomeFragmentData
}
Step 3 - Implement interface to your Activity:
class MainActivity : AppCompatActivity(), IHomeFragment {
override fun getHomeFragmentData(): HomeFragmentData {
return HomeFragmentData(
value = "Home Fragment data"
)
}
// Rest of your code
}
Step 4 - Call function getHomeFragmentData() from HomeFragment using context:
class HomeFragment : Fragment() {
private var interactionListener: IHomeFragment? = null
override fun onAttach(context: Context) {
super.onAttach(context)
when(context) {
is IHomeFragment -> {
interactionListener = context
}
else -> throw RuntimeException("$context has to implement IHomeFragment")
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
interactionListener?.getHomeFragmentData().let {
textView.text = it?.value
}
return root
}
}

Vertical Viewpager not working in kotlin android

I have been working on an app where were people can watch videos like tik tok. At first I made it with recyclerview and later on I realized that I should use Vertical Viewpager. Then I used Viewpager2 but I faced some problems so I replaced it with viewpager1. But still it is not working. I am doing this in my fragment. I want to play videos from firebase in Vertical viewpager using videoview.
In Viewpager_Adapter u can see that I have called one more layout there which is viewer_page but when I run my app I don't get that layout in my fragment
ViewpagerAdapter
class ViewpagerAdapter(var context: Context) : PagerAdapter() {
lateinit var inflater: LayoutInflater
var contentDTOs: ArrayList<ContentDTOs> = arrayListOf()
var contentUidList: ArrayList<String> = arrayListOf()
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object` as ConstraintLayout
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object`as ConstraintLayout)
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
inflater = context.getSystemService(container.context.toString())as LayoutInflater
val view =inflater.inflate(R.layout.viewer_page,container,false)
val exo : View? = view?.findViewById(R.id.videoviews)
val path = Uri.parse(contentDTOs[position].videourl)
val views = view.findViewById<VideoView>(R.id.videoviews)
views.setVideoURI(path)
views.requestFocus()
views.setOnPreparedListener {
views.start()
}
container.addView(view)
return view
}
override fun getCount(): Int {
return contentDTOs.size
}
}
Watch_video_fragment
#SuppressLint("ResourceAsColor")
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val fragmentview = inflater.inflate(R.layout.fragment_watch_video, container, false)
fragmentview.videofragment?.setOnClickListener {
var fragment = Watch_video()
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.frag, fragment)
?.commit()
}
fragmentview.memefragment?.setOnClickListener {
var fragment = DetailViewFragment()
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.frag, fragment)
?.commit()
}
firestore = FirebaseFirestore.getInstance()
uid = FirebaseAuth.getInstance().currentUser?.uid
fragmentview.videofragment?.setOnClickListener {
var fragment = Watch_video()
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.frag, fragment)
?.commit()
}
//
fragmentview.vertical_viewpager.adapter = ViewpagerAdapter(requireContext())
fragmentview.vertical_viewpager.setPageTransformer(false
) { page, position ->
page.rotationY = position * -30 // animation style... change as you want..
}
Can u guys plz help me

Problems with SmartToolbar not recreating fragments

I'm having a problem with this SmartToolbar, if I open the app and click on the chat or book icon it opens perfectly and shows the fragments, but if I click on another icon to open another fragment, when I go back to them they don't show more The fragments that should be on the smartToolbar, as shown in the prints below, bug everything! I need to help on this as soon as possible !!!
[Opens normally When I click on another item and go back to it, it no longer opens the SmartToolbar fragmentshere]2
enter image description here
I will send the homeAcitivity code, where is the layout that opens the fragments of the buttonNavigationBar
class HomeActivity : AppCompatActivity() {
var MY_ACCOUNT = 1
var LIBRARY = 2
var HOME = 3
var CHAT = 4
var SETTINGS = 5
private var Content: ConstraintLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar!!.hide()
nav.show(HOME)
nav.setBackgroundColor(Color.TRANSPARENT)
abrirHome()
addOnMeowNavigattionBarIcons()
addOnNotificationInform()
chamarFragments()
}
fun abrirHome() {
val fragment = HomeFragment.newInstance()
addFragment(fragment)
}
fun addOnMeowNavigattionBarIcons() {
nav.add(MeowBottomNavigation.Model(MY_ACCOUNT, R.drawable.ic_baseline_account_circle_24))
nav.add(MeowBottomNavigation.Model(LIBRARY, R.drawable.ic_baseline_menu_book_24))
nav.add(MeowBottomNavigation.Model(HOME, R.drawable.ic_baseline_home_24))
nav.add(MeowBottomNavigation.Model(CHAT, R.drawable.ic_baseline_chat_24))
nav.add(MeowBottomNavigation.Model(SETTINGS, R.drawable.ic_baseline_settings_24))
}
fun addOnNotificationInform() {
nav.setCount(CHAT, "99")
}
fun chamarFragments() {
nav.setOnClickMenuListener {
when (it.id) {
HOME -> {
val fragment = HomeFragment.newInstance()
addFragment(fragment)
}
MY_ACCOUNT -> {
val fragment = MyAccountFragment.newInstance()
addFragment(fragment)
}
LIBRARY -> {
val fragment = LibraryFragment.newInstance()
addFragment(fragment)
}
CHAT -> {
val fragment = ChatFragment.newInstance()
addFragment(fragment)
}
SETTINGS -> {
val fragment = SettingsFragment.newInstance()
addFragment(fragment)
}
}
}
}
private fun addFragment(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.replace(R.id.parentfragments,fragment,fragment.javaClass.simpleName)
.addToBackStack(null)
.commit()
}
fun sair(view: View){
FirebaseAuth.getInstance().signOut()
val bundle = ActivityOptions.makeSceneTransitionAnimation(this).toBundle()
val intent = Intent(this, login::class.java)
startActivity(intent,bundle)
}
}
This is the code of the fragment Library that has a SmartToolbar that calls two more fragments within it, MyLibrary and Store
class LibraryFragment: Fragment() {
companion object{
fun newInstance():LibraryFragment {
val args = Bundle()
val fragment = LibraryFragment()
fragment.arguments = args
return fragment
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.library_fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val adapter = FragmentPagerItemAdapter(
fragmentManager, FragmentPagerItems.with(context)
.add("Minha Bilioteca", MyLibraryFragment::class.java)
.add("Loja", StoreFragment::class.java)
.create())
viewpager.adapter = adapter
viewpagertab.setViewPager(viewpager)
}
}
And this is the MyLibrary fragment that is shown inside the Library that is shown inside HomeActivity
class MyLibraryFragment: Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.mylibrary_fragment, container, false)
}
}

Make a TabBar inside a specific NavBar fragment

my app use bottomNavBar with 3 fragments [Settings / Home / Gallery].
Now I'm trying to make a TabBar with 3 new Tabs inside of "Settings". [setting01 / setting02 / setting03]
I followed carefully this tutorial : https://www.youtube.com/watch?v=qfFANw7nPMU
and I used viewPager2 when the video uses viewPager.
but I'm still stuck in MainActivity.kt because for some reasons these two line (from the tutorial) didn't work for me :
viewPager2.adapter = PageAdapter(supportFragmentManager)
tabLayout.setupWithViewPager(viewPager2)
here is my entire MainActivity.kt file :
package com.example.appname
import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.appname.ui.settings.PageAdapter
import kotlinx.android.synthetic.main.fragment_settings.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_settings, R.id.navigation_swapper, R.id.navigation_gallery))
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
viewPager2.adapter = PageAdapter(supportFragmentManager)
tabLayout.setupWithViewPager(viewPager2)
}
}
I'm almost certain that this error exists because these two lines should be somewhere else because of the particular situation of my application.
To find yourself in a situation similar to mine I recommend you to start a new project under android studio using the template "Bottom Navigation Activity" and then follow the tutorial.
A friend of mine give me the solution.
Nothing new in MainActivity.kt like I was thinking.
Here is the new code to make tabBar in the Settings fragment :
settingFragment.kt
class SettingsFragmentAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
private val fragments =
listOf(
fragment_setting_teams(),
fragment_setting_general(),
fragment_setting_movies()
)
override fun getItemCount(): Int = fragments.size
override fun createFragment(position: Int): Fragment = fragments[position]
}
class SettingsFragment : Fragment() {
private lateinit var settingsViewModel: SettingsViewModel
private lateinit var settingsAdapter: SettingsFragmentAdapter
private lateinit var viewPager: ViewPager2
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val tabLayout = view.findViewById<TabLayout>(R.id.tabLayout)
settingsAdapter =
SettingsFragmentAdapter(
this
)
viewPager = view.findViewById(R.id.viewPager2)
viewPager.adapter = settingsAdapter
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
when (position) {
0 -> tab.text = "Teams"
1 -> tab.text = "General"
2 -> tab.text = "Movies"
}
}.attach()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
settingsViewModel =
ViewModelProviders.of(this).get(SettingsViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_settings, container, false)
return root
}
}

Resources