I am new to Kotlin and Android Studio. I tried implementing Fragments and Navigation in my application. Following is my code. When the Application is run, it keeps on crashing. I don't understand where I ve made mistake. The application does not show any compilation error.
MainActivity.kt :
package com.example.firstandroid
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.firstandroid.databinding.ActivityMainBinding
import androidx.navigation.fragment.NavHostFragment
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
// Get the navigation host fragment from this Activity
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
// Instantiate the navController using the NavHostFragment
val navController = navHostFragment.navController
// Make sure actions in the ActionBar get propagated to the NavController
}
StartOrder.kt :
package com.example.firstandroid
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.example.firstandroid.databinding.FragmentStartOrderBinding
class StartOrder : Fragment() {
private var binding: FragmentStartOrderBinding?=null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding=FragmentStartOrderBinding.inflate(inflater, container, false)
return binding?.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding?.StartOrderButton?.setOnClickListener{orderDish()}
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
fun orderDish(){
findNavController().navigate(R.id.action_startOrder_to_chooseDish)
}
}
chooseDish.kt :
package com.example.firstandroid
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.example.firstandroid.databinding.FragmentChooseDishBinding
class ChooseDish : Fragment() {
private var binding: FragmentChooseDishBinding?=null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding= FragmentChooseDishBinding.inflate(inflater, container, false)
return binding?.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding?.chooseDishNext?.setOnClickListener{orderSidedish()}
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
fun orderSidedish(){
findNavController().navigate(R.id.action_chooseDish_to_sidedish)
}
}
Try this Solution:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.firstandroid.databinding.ActivityMainBinding
import androidx.navigation.fragment.NavHostFragment
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
}
}
Related
I am using RecyclerView in my app. But I'm getting this error in the Logcat. Here is my Codes;
My Fragment
package com.ahmetkaan.kediy.Fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.ahmetkaan.kediy.R
import com.ahmetkaan.kediy.adapter.NotesAdapter
import com.ahmetkaan.kediy.database.NotesDatabase
import com.ahmetkaan.kediy.databinding.FragmentHomeBinding
import com.ahmetkaan.kediy.entities.Notlar
import kotlinx.coroutines.launch
import java.util.*
import kotlin.collections.ArrayList
class Home : BaseFragment() {
lateinit var binding : FragmentHomeBinding
var arrNotes = ArrayList<Notlar>()
var notesAdapter: NotesAdapter = NotesAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerView.setHasFixedSize(true)
binding.recyclerView.layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
launch {
context?.let {
val notes = NotesDatabase.getDatabase(it).noteDao().getAllNotes()
notesAdapter.setData(notes)
arrNotes = notes as ArrayList<Notlar>
binding.recyclerView.adapter = notesAdapter
}
}
binding.searchView.setOnQueryTextListener( object : SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(p0: String?): Boolean {
return true
}
override fun onQueryTextChange(p0: String?): Boolean {
var tempArr = ArrayList<Notlar>()
for (arr in arrNotes){
if (arr.not!!.toLowerCase(Locale.getDefault()).contains(p0.toString())){
tempArr.add(arr)
}
}
notesAdapter.setData(tempArr)
notesAdapter.notifyDataSetChanged()
return true
}
})
notesAdapter.setOnClickListener(onClicked)
binding.notEkle.setOnClickListener {
val action = HomeDirections.actionHome2ToNotOlustur()
Navigation.findNavController(requireActivity(), R.id.fragmentContainerView).navigate(action)
}
binding.calendar.setOnClickListener {
val action = HomeDirections.actionHome2ToCalendar2()
Navigation.findNavController(requireActivity(), R.id.fragmentContainerView).navigate(action)
}
}
private val onClicked = object :NotesAdapter.OnItemClickListener {
override fun onClicked(notesId: Int) {
val fragment: Fragment
val bundle = Bundle()
bundle.putInt("noteId", notesId)
fragment = NotOlustur.newInstance()
fragment.arguments = bundle
val action = HomeDirections.actionHome2ToNotOlustur()
Navigation.findNavController(requireActivity(), R.id.fragmentContainerView)
.navigate(action)
}
}
}
My Adapter
package com.ahmetkaan.kediy.adapter
import android.graphics.BitmapFactory
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.cardview.widget.CardView
import androidx.core.graphics.drawable.toDrawable
import androidx.recyclerview.widget.RecyclerView
import com.ahmetkaan.kediy.R
import com.ahmetkaan.kediy.entities.Notlar
import kotlin.collections.ArrayList
class NotesAdapter() :
RecyclerView.Adapter<NotesAdapter.NotesViewHolder>() {
var listener:OnItemClickListener? = null
var arrList = ArrayList<Notlar>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotesViewHolder {
return NotesViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_notlar,parent,false)
)
}
override fun getItemCount(): Int {
return arrList.size
}
fun setData(arrNotesList: List<Notlar>){
arrList = arrNotesList as ArrayList<Notlar>
}
fun setOnClickListener(listener1: OnItemClickListener){
listener = listener1
}
override fun onBindViewHolder(holder: NotesViewHolder, position: Int) {
holder.itemView.findViewById<TextView>(R.id.theNotC).text = arrList[position].not
holder.itemView.findViewById<TextView>(R.id.dateTimeC).text = arrList[position].dateTime
if (arrList[position].impPathBackground != null){
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageBitmap(BitmapFactory.decodeFile(arrList[position].impPathBackground))
} else {
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageDrawable(R.drawable.ronin.toDrawable())
}
if (arrList[position].impPathBackground != null){
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageBitmap(BitmapFactory.decodeFile(arrList[position].impPathLogo))
} else {
holder.itemView.findViewById<ImageView>(R.id.backgroundC).setImageDrawable(R.drawable.logo1.toDrawable())
}
holder.itemView.findViewById<CardView>(R.id.cardView).setOnClickListener {
listener!!.onClicked(arrList[position].id!!)
}
}
class NotesViewHolder(view:View) : RecyclerView.ViewHolder(view){
}
interface OnItemClickListener{
fun onClicked(noteId:Int)
}
}
I searched a lot on the internet but I didn't understand much because they are all in java language. It didn't work even though I tried what I understood. Unlike others, I used CoroutineScope(launch) I think it was because of it, but I'm not sure. What should i do?
Setting the adapter should be in the main thread. But you wrapped it in launch.
binding.recyclerView.adapter = notesAdapter
I am trying to get a spinner working with Kotlin, I have spent hours on it but to no avail. Whatever I do, it doesn't respond to items being selected.
Let's start with the code:
This is my xml layout: (only the spinner)
<Spinner
android:id="#+id/unitySelectionSpinner"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="50"
android:gravity="center"
android:textSize="24sp"
/>
My Fragment:
import android.app.Activity
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.navigation.Navigation
import com.epfl.esl.organizer.databinding.FragmentCreateStorageBinding
import com.google.firebase.database.*
import kotlin.collections.ArrayList
class CreateStorageFragment : Fragment(), AdapterView.OnItemSelectedListener {
private lateinit var binding: FragmentCreateStorageBinding
private lateinit var unitID: String
val database: FirebaseDatabase = FirebaseDatabase.getInstance("myDatabase")
val storageRef: DatabaseReference = database.getReference("Units")
var list = ArrayList<String>()
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
Toast.makeText(context, "We got the Key:", Toast.LENGTH_SHORT).show()
var a = 7 / 0
}
override fun onNothingSelected(parent: AdapterView<*>?) {
Toast.makeText(context, "Nothing selected", Toast.LENGTH_SHORT).show()
var b = 7 / 0
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_create_storage, container, false)
// Get the list of names of units from firebase
storageRef.addListenerForSingleValueEvent(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
// Fill an ArrayList with all the unit names
for(unit in snapshot.children) {
list.add(unit.child("unitName").value.toString())
}
}
override fun onCancelled(error: DatabaseError) {}
})
binding.addObjectButton.setOnClickListener{view: View ->
Navigation.findNavController(view).navigate(R.id.action_createStorageFragment_to_createObjectFragment)
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val spinner: Spinner = binding.unitySelectionSpinner
val spinnerArrayAdapter = ArrayAdapter<String>(activity as Context, android.R.layout.simple_spinner_dropdown_item, list)
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = spinnerArrayAdapter
spinner.onItemSelectedListener = this
}
}
I feel that I've tried everything imaginable, including:
-Creating an independent class with the spinner functions (onItemSelected, etc.)
-Put everything in onCreateView, put everything in onViewCreated
-Creating an instance of spinner with AdapterView.OnItemSelectedListener inside onCreateView
Whatever I do the result is always the same: the spinner is populated (all the firebase data is written into it properly) but it doesn't respond when I click on an item in the app. None of the toasts (or the crash that should be caused by the division by zero) are triggered. It simply closes on selection as a normal spinner would do.
I am not sure what I am missing here. Any ideas?
class MainActivity : AppCompatActivity() {
lateinit var playbutton : Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
playbutton = findViewById(R.id.play_button)
playbutton.setOnClickListener {
val intent = Intent(this,Frame::class.java)
startActivity(intent)
}
}
}
Showing Error Unreolved Reference Java
my Imports :
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
I am starting another Activity From The Mainactivity and android studio is Showing This Error .
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
}
}
I'm learning how to parse a JSON and using the data to put it in a recyclerview list and I am doing it in a fragment. This is giving lots of headhaches, and kinds of errors. The first one is the Context! this is the GroupFragment.kt file content:
package com.locos.riders
import android.graphics.Color
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.fragment_groups.*
import com.locos.riders.UserListAdapter
class GroupsFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_groups, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
userlist.layoutManager = LinearLayoutManager(this)
userlist.adapter = UserListAdapter
}
}
When I run this, I get the Type mismatch: inferred type is GroupsFragment but Context! was expected.
In my UserListAdapter.kt I am trying to load userlist_row and i also cannot find this layout resource, even that the file is created and in layout/ folder:
package com.locos.riders
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.userlist_row.view.*
class UserListAdapter: RecyclerView.Adapter<CustomViewHolder>() {
// number of items
override fun getItemCount(): Int {
return 3
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): CustomViewHolder {
val layoutInflater = LayoutInflater.from(parent?.context)
val cellForRow = layoutInflater.inflate(R.layout.userlist_row, parent, false)
return CustomViewHolder(cellForRow)
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
holder.view.listTitle?.text = "123"
}
}
class CustomViewHolder(val view: View): RecyclerView.ViewHolder(view) {
}
You have some typo errors, usually can be fixed by reading the errors.
Here is the solution of those errors:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
userlist.layoutManager = LinearLayoutManager(context) // <- context == getContext() in java
userlist.adapter = UserListAdapter() // <- put parentheses over here
}