Struggling to transition code from AppcompatActivity to Fragment. Unable to use setSupportActionBar(toolbar) - android-studio

I'm trying to transition from using AppcomatActivity to Fragment, because I'm updating my app but I've run into a problem. I get a "Unresolved reference: supportFragmentManager" and "Unresolved reference: setSupportActionBar"(That's all the Logcat shows me) when I try to run my app. Now I chose to switch to using fragments, because I also want to change the apps UI, usage is quicker than the previous version. Anyway here's my code:
Recorder Fragment
package com.khumomashapa.notes.fragments
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toolbar
import androidx.annotation.RequiresApi
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager
import com.astuetz.PagerSlidingTabStrip
import com.khumomashapa.notes.R
import kotlinx.android.synthetic.main.toolbar3.*
class RecorderFragment : Fragment() {
private var tabs: PagerSlidingTabStrip? = null
private var pager: ViewPager? = null
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.title = "Recorder";
pager = pager?.findViewById<View>(R.id.pager) as ViewPager
pager!!.adapter = MyAdapter(supportFragmentManager)
tabs = tabs?.findViewById<View>(R.id.tabs) as PagerSlidingTabStrip
tabs!!.setViewPager(pager)
val toolbar = toolbar?.findViewById<View>(R.id.toolbar) as Toolbar
toolbar.popupTheme = R.style.ThemeOverlay_AppCompat_Light
setSupportActionBar(toolbar)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_recorder, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
inner class MyAdapter(fm: FragmentManager?) : FragmentPagerAdapter(
fm!!
) {
private val titles = arrayOf(
getString(R.string.tab_title_record),
getString(R.string.tab_title_saved_recordings)
)
override fun getItem(position: Int): Fragment {
when (position) {
0 -> {
return RecordFragment.newInstance(position)
}
1 -> {
return FileViewerFragment.newInstance(position)
}
}
return null!!
}
override fun getCount(): Int {
return titles.size
}
override fun getPageTitle(position: Int): CharSequence? {
return titles[position]
}
}
companion object {
private val LOG_TAG = RecorderFragment::class.java.simpleName
}
}
The purpose of this class is to show a view pager that can switch between to other fragments I've already created. I was able to fix the other errors relating to this like the "Unresolved reference for findViewById" and the "MyAdapter class".

For a Fragment, there are actually two relevant fragment managers. Deciding which one to use depends on your use case.
The Child Fragment Manager
A fragment has a child fragment manager which is responsible for managing its child/nested fragments. You can obtain this with:
Fragment.getChildFragmentManager()
The Parent's Fragment Manager
A fragment also holds reference to it's parent's fragment manager. If the fragment is a direct child of an activity then his represents the activities fragment manager. Otherwise if the fragment is a child of another fragment, it represents the child fragment manager of the parent fragment. This can be obtained with:
Fragment.getParentFragmentManager()
Note that although Fragment has the method Fragment.getFragmentManager(), this is deprecated in favour of Fragment.getParentFragmentManager() so it shouldn't be used.
You can also technically get the activities fragment manager regardless by obtaining a reference to the fragment's activity with Fragment.getAcitivity() and then calling Activity.getSupportFragmentManager(). But generally the parent fragment manager is more useful and clear.

Related

I'm trying to run video by making a video player app with simplified controls, and having issue with findViewById

The full error message I'm getting is this: Not enough information to infer type variable T
import android.net.Uri
import android.net.Uri.*
import android.os.Bundle
import android.widget.MediaController
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Find the VideoView class by its id
val videoView = findViewById(R.id.testView)
//Creating MediaController
val mediaController = MediaController(this)
mediaController.setAnchorView(videoView)
//specify the location of media file
val uri:Uri = parse(
"android.resource://" + packageName
+ "/raw/test"
)
//Setting MediaController and URI, then starting the videoView
videoView.setMediaController(mediaController)
videoView.setVideoURI(uri)
videoView.requestFocus()
videoView.start()
}
}
Full error message i'm getting :
Not enough information to infer type variable T
Kotlin isn’t able to definitively determine what class the findViewById is trying to find, so you will need to define it yourself. Try updating your code to this, to specify that the item is a VideoView object:
val videoView = findViewById(R.id.testView) as VideoView

Android Studio Kotlin app "keeps stopping" when I run it

I am just trying to set up a spinner configured as a dropdown menu, but I can't even test my app to see if it works because every time I run it, it immediately crashes. I know that my issue is related to a null object reference at line 21 in my MainActivity.kt file. Here is the problem code:
val spinner: Spinner = findViewById<Spinner>(R.id.locations)
The id of the spinner is locations, so I'm not sure why this is coming back as a null value.
Here is also the full code for the file:
import android.app.Activity
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Spinner
import android.widget.ArrayAdapter
import android.widget.AdapterView
private var userLocation: Any = ""
private var userDestination: Any = ""
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
val spinner: Spinner = findViewById<Spinner>(R.id.locations)
val locationsAdapter: ArrayAdapter<CharSequence> = ArrayAdapter.createFromResource(
this,
R.array.rooms,
android.R.layout.simple_spinner_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
}
}
class SpinnerActivity : Activity(), AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id:Long) {
userLocation = parent.getItemAtPosition(pos)
val spinner: Spinner = findViewById(R.id.locations)
spinner.onItemSelectedListener = this
}
override fun onNothingSelected(parent: AdapterView<*>) = Unit
}
Declare spinner global for MainActivity:
private lateinit var spinner: Spinner
On the method onCreate initialise the spinner and set its adapter, I would recommend you to set the array adapter as follows:
spinner = findViewById<Spinner>(R.id.locations)
spinner.adapter = ArrayAdapter(this, R.layout.drop_down_generic_item, resources.getStringArray(R.array.rooms))
I don't really understand the SpinnerActivity you showed in the question, sorry. But in MainActivity you can set the spinner.onItemSelectedLister() as follows:
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(adapterView: AdapterView<*>?, view: View?, position: Int, p3: Long) {
val selectedRoom = adapterView?.getItemAtPosition(position)
}
override fun onNothingSelected(p0: AdapterView<*>?) {
}
}
I don't want to confuse you, but have a look at a TextInputLayout with an AutoCompleteTextView, just as a hint. :D

How to add onClickListener on images in recyclerView?

I am trying to attach onclick listener on images in this code, using Glide framework but I'm not able to find a solution for that. Can someone help with this?
Images are showing in emulator already.
Thanks in advance
package com.example.andoridlifecycle.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.example.andoridlifecycle.R
import kotlinx.android.synthetic.main.item_custom_row.view.*
class ItemAdapter(private val context: Context, private val urls: ArrayList<String>) :
RecyclerView.Adapter<ItemAdapter.ViewHolder>() {
/**
* Inflates the custom view which is designed in xml layout file
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(context).inflate(
R.layout.item_custom_row,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// Array with urls
val url = urls[position]
Glide.with(context)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.drawable.placeholder)
.into(holder.imageView)
}
// Gets the number of items in the list
override fun getItemCount(): Int {
return urls.size
}
// A ViewHolder describes an item view and metadata about its place within the RecyclerView.
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val imageView: ImageView = view.iv_image
}
}
I'm Java Developer so I cannot code with Kotlin but I'll show you how to set OnClickListener on your imageView. For using OnclickListener on imageView no need for Glide Library.
Just add the below lines in your onBindViewHolder
holder.imageView.setOnClickListener(view -> {
Toast.makeText(context, "this is number: "+position+" Image Selected", Toast.LENGTH_SHORT).show();
// or your code for imageView
});
Your new code looks like the below:-
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// Array with urls
val url = urls[position]
//code for onClick on image
holder.imageView.setOnClickListener(view -> {
Toast.makeText(context, "this is number: "+position+" Image Selected", Toast.LENGTH_SHORT).show();
// or your code for imageView
});
Glide.with(context)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.drawable.placeholder)
.into(holder.imageView)
}
Make sure to change JAVA to Kotlin in my code. If you any problem is causing, Let me know

Can one reference id directly in kotlin?My small program can't seem to run

Hi im new in android and i read that i can directly reference id from activity_main to mainAcctivity.kt without using findviewbyid.When i do that i get an error but my ids are correct:
This is the error Unresolved reference: button and Unresolved reference: textView
This is my code
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// get reference to button
//val btnClickMe = findViewById(R.id.button) as Button
//val myTextView = findViewById(R.id.textView) as TextView
var timesClicked = 0
// set on-click listener
button.setOnClickListener {
timesClicked += 1
textView.text = timesClicked.toString()
Toast.makeText(this#MainActivity, "Hello Don.", Toast.LENGTH_SHORT).show()
}
}
}```
Please help out,i tried to import android.widget.button and textView that option is not available but when i hardcode the text appears inactive.
You can make use of ViewBinding to reduce the use of findViewById. You can find an example here.
You can go through this blog to have more insight on how to use ViewBinding.
For the above code, you can resolve the issue using the code below:
val myTextView = findViewById<TextView>(R.id.textView)
val btnClickMe = findViewById<Button>(R.id.button)

Kotlin AddOnPageChangeListener not working

I wanted to connect a viewPager with an adapter (like this: viewPager.addOnPageChangeListener()), but the letters of the pageChangeListener just turn red like it wasn't a valid code...What am I doing wrong?? Heres a screenshot:
[1]: https://i.stack.imgur.com/IOYJY.png
Context: I'm currently working on a game with a few fragments where you can choose your game cards. I need the pageChangeListener to change the pictures of them cards. Maybe there could be another way to do this but i don't know how...
package com.suffv1
import android.os.Bundle
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import com.example.suff_02.Adapter2
import com.example.suff_02.R
import com.example.suff_02.kartenmodell
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity(){
private lateinit var actionbar: ActionBar
private lateinit var liste: ArrayList<kartenmodell>
private lateinit var myAdapter: Adapter2
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
super.setContentView(R.layout.activity_main)
actionbar = this.supportActionBar!!
loadCards()
viewpager2.addOnPageChangeListener(object: ViewPager.OnPageChangeListener{
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
val title = liste[position].KartenImage
actionbar.title = title
}
})
}
private fun loadCards() {
liste = ArrayList()
liste.add(kartenmodell(R.drawable.bier_radler_klein_level_1))
liste.add(kartenmodell(R.drawable.bier_hopfentrunk_klein_level_1))
liste.add(kartenmodell(R.drawable.bier_butt_light_klein_level_1))
liste.add(kartenmodell(R.drawable.bier_becks_klein_level_1))
liste.add(kartenmodell(R.drawable.bier_tyskie_klein_level_1))
myAdapter = Adapter2(this, liste)
viewpager2.adapter = myAdapter
viewpager2.setPadding(100, 0, 100, 0)
}
}
Looks like you are using ViewPager2 not the original Viewpager and Viewpager2 does not have Page Change Listeners it instead has Page Change Callbacks
So you are using the wrong method to get notified when a pages is changed.
Instead do something like
var myPageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
Toast.makeText(this#MainActivity, "Selected position: ${position}",
Toast.LENGTH_SHORT).show()
}
}
viewpager.registerOnPageChangeCallback(myPageChangeCallback)
Though architecturally a lot of times it is bad form to use a OnPageChangeCallback as you are likely breaking the encapsulation idea of the Fragment and it can be better to use the lifecycle state change to Resumed of the Fragment to do things when a page(Fragment) is selected. e.g. put the code in the Fragments onResume method.
Though in this case of setting the actionbar title it is probably ok architecturally to use a OnPageChangeCallback
To create a AddOnPageChangeListener(), you do it as:
//See how, you have to use object to create an Object of the interface OnPageChangeListener.
//This is how you do for other listeners/interfaces/class as well when you've to implement its member functions instead of new in java.
viewPager.addOnPageChangeListener(object: ViewPager.OnPageChangeListener{
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
TODO("Not yet implemented")
}
override fun onPageSelected(position: Int) {
TODO("Not yet implemented")
}
override fun onPageScrollStateChanged(state: Int) {
TODO("Not yet implemented")
}
})
But, further in Kotlin, you can use Kotlin functions as
//This is for onPageSelected only.
viewPager.onPageChangeListener{ position: Int ->
//This position is the selected Page's position
}

Resources