how to change the text value in a textview, whilst in a fragment. Kotlin - android-studio

Does anyone know of a way to change the value of a textview text, whilst in a fragment. I have tried findviewbyid, however i believe that this does not work whilst in a fragement. Does anyone have an idea on how to identify a textview and change the text value of it. Thanks
class Home : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_home, container, false)
val queue = Volley.newRequestQueue(view.context)
val url = "https://io.adafruit.com/api/v2/alex9301/feeds/test-data/data" //URL
var urlStuff = ""
val stringRequest = StringRequest(Request.Method.GET, url,
{ response ->
// Display the first 500 characters of the response string.
urlStuff = response
val jsonArray = JSONTokener(urlStuff).nextValue() as JSONArray
val id = jsonArray.getJSONObject(0).getString("value") // Get data
Log.i("Val: ", id)
//Updating info on app
val textView = view.findViewById(R.id.temp)
textView.text = "My Text"
},
{ Log.i("b", "That didn't work!") })
queue.add(stringRequest)
return view
}
}

findViewById also works in a fragment, like this:
val view = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = view.findViewById(R.id.temp)
textView.text = "My Text"

Related

I don't know why this app is shutting down(because of databinding,setOnClickListener)

class day_1 : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var _binding: FragmentDay1Binding? = null
private val binding get() = _binding!!
private var mediaPlayer: MediaPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
binding.startbutton.setOnClickListener {
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(activity, R.raw.days)
}
mediaPlayer?.start()
}
binding.pausebutton.setOnClickListener {
if (mediaPlayer?.isPlaying == true) {
mediaPlayer?.pause()
} else {
mediaPlayer?.start()
}
}
binding.stopbutton.setOnClickListener {
mediaPlayer?.stop()
mediaPlayer = null
}
fun onStop() {
super.onStop()
mediaPlayer?.release()
mediaPlayer = null
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = FragmentDay1Binding.inflate(inflater,container,false)
return binding.root
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment day_1.
*/
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String, param2: String) =
day_1().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
what is above is my code. If I click the button, application was shutting down. First, I think that Media Player is problem. but application without setOnClickListener has no problem. Please help me masters.... Is it problem that setOnClickListener is in Fragment?
And Can I amend this code? or I restart project? Perhaps If you know why this problem exist, Please tell me resolution...
You can take a look for fragment lifecycles at here https://developer.android.com/guide/fragments/lifecycle
You are setting on click listener at onCreate method, in fragments views are created at onCreateView method so you are trying to access your view before it is created. So instead of onCreate method you need to set your click listener after your binding/view is ready, for example you can set your click listener before returning binding.root at onCreateView. Also you can set your click listener at onViewCreated method.

How to open a different activity on recyclerView in fragment?

I am using a recyclerView to show my listItems in the home fragment. But I have been stuck on how to open a different activity when items are clicked. How can I do for the next steps? Could you please help me to solve the issue? I would appreciate the help.
HomeFragment.kt
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
lateinit var recycle1:RecyclerView
private val list = ArrayList<Locations>()
private val adapter:Adapter = Adapter(list)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
var v =inflater.inflate(R.layout.fragment_home, container, false)
recycle1 = v.findViewById(R.id.rv_item)
recycle1.layoutManager = LinearLayoutManager(activity)
list.clear()
testData()
val adapterr = Adapter(list)
recycle1.adapter = adapterr
adapter.notifyDataSetChanged()
recycle1.setHasFixedSize(true)
return v
}
private fun testData(){
list.add(Locations(R.drawable.book_cafe,"The Book Cafe","20 Martin Rd","Cafe"))
list.add(Locations(R.drawable.citysprouts,"City Sprouts","102 Henderson Road","Cafe"))
list.add(Locations(R.drawable.esplanade,"Library#esplande","8 Raffles Ave","Library"))
list.add(Locations(R.drawable.hf,"Library#Harbourfront","1 HarbourFront Walk","Library"))
list.add(Locations(R.drawable.mangawork,"MangaWork","291 Serangoon Rd","Cafe"))
list.add(Locations(R.drawable.orchard,"Library#orchard","277 Orchard Road","Library"))
list.add(Locations(R.drawable.rabbitandfox,"Rabbit&Fox","160 Orchard Rd","Cafe"))
list.add(Locations(R.drawable.sixlettercoffee,"T6 Letter Coffee","259 Tanjong Katong Rd","Cafe"))
}
}
Adapter.kt
class Adapter (val listItem:ArrayList<Locations>) : RecyclerView.Adapter<Adapter.RecycleViewHolder>(){
inner class RecycleViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
val itemImage: ShapeableImageView = itemView.findViewById(R.id.item_image)
val heading: TextView = itemView.findViewById(R.id.item_title)
val detail: TextView = itemView.findViewById(R.id.item_detail)
val category: TextView = itemView.findViewById(R.id.item_categories)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecycleViewHolder {
val view:View = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return RecycleViewHolder(view)
}
override fun getItemCount(): Int {
return listItem.size
}
override fun onBindViewHolder(holder: RecycleViewHolder, position: Int) {
val item = listItem[position]
holder.itemImage.setImageResource(item.itemImage)
holder.heading.text = item.headings
holder.detail.text = item.detail
holder.category.text = item.category
}
Locations. kt
data class Locations(var itemImage:Int,var headings :String,var detail :String,var category :String)
You have to take help of an interface to navigate :
First Create an interface , Suppose name it Navigate
interface Navigate {
fun onRecyclerViewItemClicked(location : Location)
}
Then you have to make use of this interface in the adapter as well as the fragment :
In your adapter , you have to do the following :
class Adapter (val listItem:ArrayList<Locations>) : RecyclerView.Adapter<Adapter.RecycleViewHolder>(){
//Declare listener object
var listener: Navigate? = null
inner class RecycleViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
val itemImage: ShapeableImageView = itemView.findViewById(R.id.item_image)
val heading: TextView = itemView.findViewById(R.id.item_title)
val detail: TextView = itemView.findViewById(R.id.item_detail)
val category: TextView = itemView.findViewById(R.id.item_categories)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecycleViewHolder {
val view:View = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return RecycleViewHolder(view)
}
override fun getItemCount(): Int {
return listItem.size
}
override fun onBindViewHolder(holder: RecycleViewHolder, position: Int) {
val item = listItem[position]
holder.itemImage.setImageResource(item.itemImage)
holder.heading.text = item.headings
holder.detail.text = item.detail
holder.category.text = item.category
// Now suppose you want to navigate to another fragment / Activity on click of the itemImage , then do the following
holder.itemImage.setOnClickListener{
listener?.onRecyclerViewItemClicked(item)
}
}
Now in your fragment extend the Navigate Class and implement the override the methods :
class HomeFragment : Fragment() , Navigate {
// Rest of your code
override fun onRecyclerViewItemClicked(location : Location){
// The argument location here is the information of the item that is clicked of
// the RecyclerView
// Here write your code to navigate to the next fragment / activity based on what
//you are using NavController / Fragment Manager
}
}
Set a clickListener in init {} block of your view holder
For eg.
inner class RecycleViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
val itemImage: ShapeableImageView = itemView.findViewById(R.id.item_image)
val heading: TextView = itemView.findViewById(R.id.item_title)
val detail: TextView = itemView.findViewById(R.id.item_detail)
val category: TextView = itemView.findViewById(R.id.item_categories)
init {
itemView.setOnClickListener { // start your activity using view context }
}
}
Never set your click listener in onBindViewHolder() method as click listener will set multiple times because this method method is called every time items are bound in recycler view.
Reference official doc

Hot to navigate to activity from fragment

This is my first post, so I will try to explain myself the best I can.
This is my first project in android with kotlin, and Im creating a simple app with 3 tabs. Im trying to make a simple navigation from a button in one of the 3 fragments associated with the 3 tab views to a new activity. This button have the function "push" associated.
I attach the code from the fragment, where you can see the function to navigate "push" which start the new activity. If I place that function in the onCreateView section, it works fine when I enter the fragment. I had no problem doing this navigation from an activity to another using a similar button and function but i dont know how fragments properly works, so i guess there is a thing relative to them i am missing. It seems like the function is not recognized outside the onCreate section, so maybe i have to declare it in another way:
class NotificationsFragment : Fragment() {
private var _binding: FragmentNotificationsBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentNotificationsBinding.inflate(inflater, container, false)
return binding.root
}
private val binding get() = _binding!!
fun push(view: View) {
val intent = Intent(activity, tutorialPrueba::class.java)
startActivity(intent)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
I was not able to find any solution that helps me in this case. As long this is my first post, i will thank any help or recommendation relative to the way I posted or how i can make it better. Also sorry for my poor english.
Thanks in advance.
If you are using the DataBinding, the onClick declared in the layout xml does not work. So to make the button, once pressed, call your method you have to do this:
private var _binding: FragmentNotificationsBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentNotificationsBinding.inflate(inflater, container, false)
_binding.idOfButtonToPress.setOnClickListener{ //replace idOfButtonToPress with the real android:id of button
push()
}
return binding.root
}
private val binding get() = _binding!!
fun push() {
val intent = Intent(activity, tutorialPrueba::class.java)
startActivity(intent)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

Inflate multiples views into a fragment

I was working on my app and i need to make a list of little groups of views like this :
(i couldn't post my image 'cause StackOverflow thing i'm not famous enought)
IMAGE
The fragment is shown , and correctly applied but the view group that i'm trying to display doesn't.
I can't find how to make my fragment apprear and make the buttons work (But that's not the point now , so I'll ask the question later)
class EditFragment : Fragment() {
lateinit var option : Spinner
lateinit var result : TextView
private lateinit var viewOfLayout: View
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewOfLayout = inflater.inflate(R.layout.edit_fragment, container, false)
val mainLayout = viewOfLayout.findViewById(R.id.scrollView1) as ScrollView
//create a view to inflate the layout_item (the xml with the textView created before)
val view = layoutInflater.inflate(R.layout.sensor_item, mainLayout, false)
val options = arrayOf("A","V")
option = view.spinner as Spinner
result = view.textView7 as TextView
option.adapter = ArrayAdapter<String>(activity,android.R.layout.simple_list_item_1,options)
return viewOfLayout
}
}
Here is the full code : https://pastebin.com/fYyXkupM
(I precise that my fragment is displaying properly)
-> I think my error is comming from there :
val view = layoutInflater.inflate(R.layout.sensor_item, mainLayout, false)
if i replace "mainLayout" by "container" it does works but it's not the fragment's child.
Thank you.
You haven't initialized option Spinner from viewOfLayout.
ok , even if that's a little specific , i found my answer :
val view = layoutInflater.inflate(R.layout.sensor_item, container, false)
val insertPoint = viewOfLayout.findViewById(R.id.box_Parent) as LinearLayout
insertPoint.addView(view2, 0)

kotlin.TypeCastException: null cannot be cast to non-null type error

I'm trying to get a info box working with Google Maps API. When trying to run the application, and adding a marker with custom info box it crashes.
Here is my code:
class MainMapsActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mMap: GoogleMap
private val test: ArrayList<String> = arrayListOf()
private var mLocationPermissionGranted: Boolean = false
private val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: Int = 1234
// ^Number isnt definitive, as long as its unique inside the application
private val DEFAULT_ZOOM: Float = 15.0F
private var mLastKnownLocation: Location? = null
private val mDefaultLocation = LatLng(60.312491, 24.484248)
private lateinit var mFusedLocationProviderClient: FusedLocationProviderClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main_maps)
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
val mapFragment = supportFragmentManager
.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this)
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
}
override fun onMapReady(googleMap: GoogleMap) {
mMap = googleMap
getDeviceLocation()
//PRESSING WILL ADD MARKER
mMap.setOnMapClickListener(GoogleMap.OnMapClickListener { point ->
val builder: AlertDialog.Builder
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert)
} else {
builder = AlertDialog.Builder(this)
}
val marker = MarkerOptions().position(point)
builder.setTitle("Are you sure you want to add a map location here?")
.setMessage("Are you sure you want to add a map location here?")
.setPositiveButton(android.R.string.yes, DialogInterface.OnClickListener { dialog, which ->
mMap.addMarker(marker)
//CUSTOM MARKER
.setIcon(BitmapDescriptorFactory.fromResource(R.mipmap.pinetree_foreground))
})
.setNegativeButton(android.R.string.no, DialogInterface.OnClickListener { dialog, which ->
// do nothing
})
.show()
true
val mapInfoWindowFragment = supportFragmentManager.findFragmentById(R.id.infoWindowMap) as MapInfoWindowFragment
//Set Custom InfoWindow
val infoWindow = InfoWindow(point, InfoWindow.MarkerSpecification(0, 0), mapInfoWindowFragment)
// Shows the InfoWindow or hides it if it is already opened.
mapInfoWindowFragment.infoWindowManager()?.toggle(infoWindow, true);
})
And here is the error Logcat gives me:
kotlin.TypeCastException: null cannot be cast to non-null type com.example.sampo.luontoalueet.MapInfoWindowFragment
at com.example.sampo.luontoalueet.MainMapsActivity$onMapReady$1.onMapClick(MainMapsActivity.kt:123)
My question is how to change change this statement into non-null type?
val mapInfoWindowFragment = supportFragmentManager.findFragmentById(R.id.infoWindowMap) as MapInfoWindowFragment
Your findfragmentById is returning null (which indicates that your fragment does not exist).
If you're absolutely sure that fragment cannot be null at this point, you need to review your code. Maybe your fragment is not attached to supportFragmentManager?
If you want to handle a case where this fragment might not exist, You can use nullable cast as?:
val mapInfoWindowFragment = supportFragmentManager.findFragmentById(R.id.infoWindowMap) as? MapInfoWindowFragment
Then you can check conditionally if(mapInfoWindowFragment == null) and handle the null case.

Resources