I made a listview in a fragment
There is a null pointer exception for the adapter of the list view
But the Arraylist and the adapter are not null.
Error: lvElevator cannot be null
The error is for the below line
lvElevator.adapter = EAdapter
Fragment Class
var EList=ArrayList<E1List>()
class EDetails: Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
EList.add(E1List(1))
EList.add(E1List(2))
var EAdapter = EleAdapter(EList)
lvElevator.adapter = EAdapter
return inflater.inflate(R.layout.fragment_elevators, container, false)
}
inner class EleAdapter : BaseAdapter {
var EListAdapter = ArrayList<E1List>()
constructor(EListAdapter: ArrayList<E1List>) : super() {
this.EListAdapter = EListAdapter
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var myView = layoutInflater.inflate(R.layout.elevator_ticket, null)
var myEle = EListAdapter[position]
myView.tvEnum.text = myEle.elevatornum.toString()
return myView
}
override fun getItem(position: Int): Any {
return EListAdapter[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return EListAdapter.size
}
}
}
You are trying to define lvElevator before fragment inflate the xml layout file.
There is two way to fix it.
1) Use onViewCreated() method instead to load data into views. And use onCreateView method to just inflate the view only.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
EList.add(E1List(1))
EList.add(E1List(2))
var EAdapter = EleAdapter(EList)
lvElevator.adapter = EAdapter
}
2) Modify onCreateView() method like below.
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Define views manually..
val view = inflater.inflate(R.layout.fragment_elevators, container, false)
val lvElevator = view.findViewById<ListView>(R.id.lvElevator)
EList.add(E1List(1))
EList.add(E1List(2))
var EAdapter = EleAdapter(EList)
lvElevator.adapter = EAdapter
return view
}
As an experienced developer, I would recommended to use the first way as that method will only come in scope after layout completely inflated.
Related
I implemented a simple recyclerview using databinding using kotlin language.
In xml, recyclerview seems to be the default,
but when I run it, it doesn't show up as default.
Other buttons and views included in the fragment appear normally when executed, but only the recyclerview is not visible. Which part is wrong?
class WorkFragment : Fragment() {
private var _binding: FragmentWorkBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentWorkBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val data = mutableListOf<WorkList>()
val adapter = WorkAdapter()
adapter.data = data
binding.recycler1.adapter = adapter
binding.recycler1.layoutManager = LinearLayoutManager(requireContext())
}
}
class WorkAdapter : RecyclerView.Adapter<WorkAdapter.ViewHolder>() {
var data = mutableListOf<WorkList>()
class ViewHolder(val binding: RecyclerviewWorkItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(workList: WorkList) {
binding.tvStarttime.text = workList.Starttime
binding.tvAdmin.text = workList.Admin
binding.tvPart.text = workList.Part
binding.tvStoptime.text = workList.Stoptime
binding.tvWorkers.text = workList.Workers.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WorkAdapter.ViewHolder {
val binding = RecyclerviewWorkItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: WorkAdapter.ViewHolder, position: Int) {
holder.bind(data[position])
}
override fun getItemCount(): Int {
return data.size
}
// fun replaceList(newList: MutableList<WorkList>) {
// data = newList.toMutableList()
// notifyDataSetChanged()
// }
}
Is there something wrong with my code?
For reference, I just used a fragment, not an activity.
its typically for the RecyclerView to behave like its hidden but actually its not. the reason is you are passing an empty list so the recycler will not be extended or show because there is no items in the list.
I am currently working on a simple journal app where the user can make new entries, which get stored into a room database and displayed through a RecyclerView using cards. I am currently trying to implement a way to filter card entries based on the text within them using a SearchView. However, everything that I've found online seems to be entirely in Java, just filtering a list, etc, so I'm not sure how I would go about doing this. Any help would be massively appreciated!
Here is my code (without imports):
Fragment that displays entries through RecyclerView:
class HomeFragment : BaseFragment() {
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)
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recycler_view.setHasFixedSize(true)
recycler_view.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
launch {
context?.let {
var journal = JournalDatabase.getDatabase(it).JournalDao().allJournal()
recycler_view.adapter = JournalAdapter(journal)
}
}
newEntryButton.setOnClickListener {
Navigation.findNavController(view).navigate(R.id.action_nav_home_to_nav_new_entry)
}
}
}
My adapter:
class JournalAdapter(val arrList: List<Journal>) :
RecyclerView.Adapter<JournalAdapter.JournalViewHolder>() {
class JournalViewHolder(view: View) : RecyclerView.ViewHolder(view) {
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JournalViewHolder {
return JournalViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_entry, parent, false))
}
override fun onBindViewHolder(holder: JournalViewHolder, position: Int) {
holder.itemView.rvTitle.text = arrList[position].title
holder.itemView.rvText.text = arrList[position].journalText
holder.itemView.rvDateTime.text = arrList[position].dateTime
}
override fun getItemCount(): Int {
return arrList.size
}
}
I'm getting E/RecyclerView: No adapter attached; skipping layout all the time.
Gave my best on my own, but didn't seem to get it fixed.
Browsing here for a while and found some similar problems, but I don't know what to change in my specific
case.
If you need more info feel free to ask.
class ProdItemAdapter(private val prodList: List<ProduktItem>) :
RecyclerView.Adapter<ProdItemAdapter.ProdItemViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProdItemViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.card_view_prod, parent, false)
return ProdItemViewHolder(itemView)
}
override fun onBindViewHolder(holder: ProdItemViewHolder, position: Int) {
val currentItem = prodList[position]
holder.cvProdName.text = currentItem.name
holder.cvProdCode.text = currentItem.code
}
override fun getItemCount() = prodList.size
class ProdItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val cvProdName: TextView = itemView.cv_name
val cvProdCode: TextView = itemView.cv_code
}
}
RecyclerView-Adapter: Adding some Breakpoints inside this class, all get passed.
class FragProd : Fragment() {
private var param1: Int? = null
private var listener: OnFragmentInteractionListener? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getInt(ARG_SECTION_NUMBER)
}
val pl = getList()
rvProd.adapter = ProdItemAdapter(pl)
rvProd.layoutManager = LinearLayoutManager(context)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_frag_prod, container, false)
}
.......................
Fragment
Try this code, call your adapter in OnCreateView.
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
View view = inflater.inflate(R.layout.fragment_frag_prod, container, false)
val pl = getList()
rvProd.adapter = ProdItemAdapter(pl)
rvProd.layoutManager = LinearLayoutManager(context)
return view
}
I'm new to Kotlin and I'm just trying to figure out how to use spinners in a fragment.
So I guess the code below is how I should initialize the spinner but how do I point this to my premade strings in R.array and how do I capture the selections on button click. Thanks.
class paychart : Fragment() {
private lateinit var paychartview: View
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
paychartview = inflater.inflate(R.layout.fragment_paychart, container, false)
}
val yearspinner = paychartview.findViewById<Spinner>(R.id.spinneryear)
}
Use ArrayAdapter.createFromResource
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val paychartview = inflater.inflate(R.layout.fragment_paychart, container, false)
val spinner = paychartview.findViewById<Spinner>(R.id.spinneryear)
spinner?.adapter = ArrayAdapter.createFromResource(activity, R.array.string_array, android.R.layout.simple_spinner_item) as SpinnerAdapter
spinner?.onItemSelectedListener = object :AdapterView.OnItemSelectedListener{
override fun onNothingSelected(parent: AdapterView<*>?) {
//..
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val item = parent?.getItemAtPosition(position).toString()
//..
}
}
return paychartview
}
I'm having problems that all my fragments are called when the application start so when I do toast on the the second fragment it appear on the first fragment
here is my activity code
class HomePage : AppCompatActivity() {
var adapter: FPA? = null
val manager = supportFragmentManager
private lateinit var drawer: DrawerLayout
private lateinit var toggle: ActionBarDrawerToggle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(null)
setContentView(R.layout.home_page_act)
adapter = FPA(supportFragmentManager)
container.adapter = adapter
container.addOnPageChangeListener(android.support.design.widget.TabLayout.TabLayoutOnPageChangeListener(tabs))
tabs.addOnTabSelectedListener(android.support.design.widget.TabLayout.ViewPagerOnTabSelectedListener(container))
}
class FPA(fm: FragmentManager) : FragmentPagerAdapter(fm) {
override fun getItem(position: Int): Fragment {
if(position==0 )
return TrainingForSale()
else if(position==1)
return Shops()
else
return Health()
}
override fun getCount(): Int {
return 3
}
}
fun ShowFramentShops (){
val transaction = manager.beginTransaction ()
val fragmet = Shops()
transaction.replace(R.id.container,fragmet)
transaction.addToBackStack(null)
transaction.commit()
}
}
and here is my fragment pages
fragment (1)
class Shops : Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater!!.inflate(R.layout.shops_fragment, container, false)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onCreate(null);
//UserInformation.TrainingFilter=""
//UserInformation.TrainingList.clear()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(null)
Toast.makeText(activity,"Shopes",Toast.LENGTH_LONG).show()
}
}// Required empty public constructor
my second fragment
class Health : Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater!!.inflate(R.layout.health_fragment, container, false)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onCreate(null);
super.onViewCreated(view, savedInstanceState)
Toast.makeText(activity,"Health", Toast.LENGTH_LONG).show()
}
}// Required empty public constructor
So when I run the the app both toast appears in the same page
The ViewPager will not only create the current page, but also the some before or after. With setOffscreenPageLimit(int) you can adapt these values a little.
Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.