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
}
Related
I'm trying to add options to spinner while using databinding in fragment but it's not working, I can't understand why
class AddTransaction: Fragment() {
private var _binding: TransactionAddFragmentBinding? = null
private val binding get() = _binding!!
lateinit var spinner: Spinner
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = TransactionAddFragmentBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
fun spinner() {
spinner = binding.spinnerCategory
spinner.adapter = ArrayAdapter.createFromResource(
requireContext(), R.array.categories, R.layout.transaction_add_fragment)
}
}
Based on what you have posted, you are most likely never calling your spinner() function, which means you never set the adapter so it remains empty.
You were also passing R.layout.transaction_add_fragment to the spinner adapter, which is probably not what you wanted. The layout resource you pass in there should be for the spinner row.
Instead of putting it in a separate function, just add it to onViewCreated, like this:
class AddTransaction: Fragment() {
private var _binding: TransactionAddFragmentBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = TransactionAddFragmentBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// set the adapter here, and there is no need to make a separate "spinner"
// class member since "binding" is already a class member that contains
// the spinner
binding.spinnerCategory.adapter = ArrayAdapter.createFromResource(
requireContext(), R.array.categories, android.R.layout.simple_spinner_item)
}
}
I'm trying to create a fragment with a ListView with the id=lv and the ArrayAdapter doesn't seem to work
this is the fragment code
class Istoric : Fragment() {
var array = arrayOf("item1","item2")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val adapter = ArrayAdapter(this,R.layout.listview_item,array)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_istoric, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val lv1: ListView = view.findViewById(R.id.lv)
lv1.setAdapter(adapter)
}
}
You need to pass context instead of this
val adapter = ArrayAdapter(requireContext(), R.layout.listview_item, array)
In an android app I have an activity with several fragments. In one of these fragments I have an ImageButton. On click I want to let something happen in the activity directly, not in the fragment. In this case I want to set an image. Summed up, the ImageButton is in the fragment, but the ImageView I want to change on click is in the activity.
How do I achieve that? Whatever I've tried resulted in an app crash.
This is how my fragment.kt looks:
class Fragment1 : Fragment() {
companion object{
fun newInstance() = Fragment1()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_1, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
imageButton.setOnClickListener{
imageView.setImageResource(R.drawable.example)
}
}
}
class Fragment1 : Fragment() {
var callbacks: OnFragmentCallbacks? = null
override fun onAttach(context: Context?) {
super.onAttach(context)
callbacks = activity as OnFragmentCallbacks
}
interface OnFragmentCallbacks{
fun changeImage(resourceId: Int)
}
companion object{
fun newInstance() = Fragment1()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_1, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
imageButton.setOnClickListener{
callbacks?.changeImage(R.drawable.example)
}
}
In your Activity:
// Change FragmentName with name of your Fragment class
class MainActivity : AppCompatActivity(), FragmentName.OnFragmentCallbacks{
override fun changeImage(resouseId: Int){
imageView.setImageDrawable(getResources().getDrawable(resourceId))
// or
imageView.setImageResource(resourceId)
}
Just coded it in stackoverflow, may not be perfect
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.
class HomeFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val v = inflater.inflate(R.layout.fragment_home, container, false)
val fab = v.findViewById(R.id.fab) as FloatingActionButton
fab.setOnClickListener {
val blankFragment = BlankFragment()
val manager = childFragmentManager
manager.beginTransaction().replace(R.id.frame_container, blankFragment, blankFragment.tag).commit()
// System.out.println("You have reached the floating action button")
}
return v
}
}
Getting a no view found error. I may have issues with the R.id.frame_content but Kotlin doesn't immediately identify all id values...
This may not be the best way and I apologize for the horrible formatting I does this while answer out on my phone and it's hard to get it perfect. Anyways In the activity that holds your fragments, such as MainActivity.kt add...
supportFragmentManager.beginTransaction.add(R.id.fragment_home, HomeFragment.newInstance, "HomeFragment").commit()
In your HomeFragment.kt change the following.
class HomeFragment: Fragment(){
companion object {
fun newInstance(): HomeFragment{
return HomeFragment() }
fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view: View = inflater!!.inflate(R.layout.fragment_home, container, false)
val activity = activity
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val clickListener = View.OnClickListener { view ->
when (view.getId()) {
R.id.fab -> NextFragment()
}
}
fab.setOnClickListener(clickListener)
}
NextFragment(){
val fragManager = activity?.supportFragmentManager
fragManager?.beginTransaction()?.replace(R.id.frame_container, BlankFragment.newInstance(), "blankFragment")?.commit()
}
Make sure you make the same changes to BlankFragment.kt
class BlankFragment: Fragment(){
companion object {
fun newInstance(): BlankFragment{
return BlankFragment() }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view: View = inflater!!.inflate(R.layout.fragment_blank, container, false)
val activity = activity
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//Do some stuff with your views in BlankFragment here
}
}