Kotlin Android Studio - ListView In Fragment - android-studio

I couldn't implement list view in Fragment. I have just a ListView and ArrayList. My ArrayList is a String and takes 5 name.
class GroupFragment : Fragment() {
companion object {
fun newInstance(): GroupFragment {
return GroupFragment() } }
var arrayList= ArrayList<String>()
private lateinit var Adapter: ArrayAdapter<String>
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view: View = inflater.inflate(R.layout.fragment_group, container, false)
val activity = activity as Context
val listview = view.findViewById<ListView>(R.id.list_view)
arrayList.add("Ajay")
arrayList.add("Vijay")
arrayList.add("Prakash")
arrayList.add("Rohan")
arrayList.add("Vijay")
Adapter = ArrayAdapter(activity, android.R.layout.simple_list_item_1,arrayList )
listview.adapter = ChatAdapter(activity, android.R.layout.simple_list_item_1, arrayList)
return view
}
class ChatAdapter(var mCtx: Context, var resources:Int, var items:List<String>):ArrayAdapter<String>(mCtx, resources, items) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val layoutInflater:LayoutInflater = LayoutInflater.from(mCtx)
val view:View = layoutInflater.inflate(resources, null)
val titleTextView: TextView = view.findViewById(R.id.textView)
var mItem: String = items[position]
titleTextView.text = mItem
return super.getView(position, convertView, parent)
}
}
}
My code as above but it returns nothing. I didn't understand why ?? Is it a problem "Adapter" ?? Is there any problem context ??

Can you try directly
listview.adapter = ArrayAdapter(activity, android.R.layout.simple_list_item_1,arrayList )

Related

Can i monitor a variable changed in another class in kotlin?

Im in a fragment1 and i want go to fragment2 if an event occurred in a class called from the fragment1. I have tried a callback of fuction: function in Class call a function in fragment1 to go in fragment but i collect this error:
Process: com.example.ilmiogioco, PID: 7992java.lang.IllegalStateException: Method addObserver must be called on the main thread
at androidx.lifecycle.LifecycleRegistry.enforceMainThreadIfNeeded(LifecycleRegistry.java:317)
at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:172)
at androidx.savedstate.SavedStateRegistryController.performRestore(SavedStateRegistryController.java:61)
at androidx.navigation.NavBackStackEntry.<init>(NavBackStackEntry.java:88)
at androidx.navigation.NavBackStackEntry.<init>(NavBackStackEntry.java:73)
at androidx.navigation.NavController.navigate(NavController.java:1138)
at androidx.navigation.NavController.navigate(NavController.java:944)
at androidx.navigation.NavController.navigate(NavController.java:877)
at androidx.navigation.NavController.navigate(NavController.java:863)
at androidx.navigation.NavController.navigate(NavController.java:851)
at com.example.ilmiogioco.FullscreenFragmentSolo.follow(FullscreenFragmentSolo.kt:77)
at com.example.ilmiogioco.Solo.SpaceView.update(SpaceView.kt:276)
at com.example.ilmiogioco.Solo.SpaceView.run(SpaceView.kt:120)
at java.lang.Thread.run(Thread.java:919)
EDIT: I have fullscreenfragmentsolo (fragment1) that want in gameoverfragment (fragment2) if the class spaceview called in fullscreenfragmentsolo collect a lost game. The function follow() is called by spaceview for return in fullscreenfragmentsolo (maybe this is the thread error).
class FullscreenFragmentSolo : Fragment() {
private var spaceView: SpaceView? = null
private lateinit var backgroundMusic: MediaPlayer
private lateinit var window: Window
private var binding: FragmentFullscreenSoloBinding? = null
object size{
var x = 0
var y = 0
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
(activity as AppCompatActivity?)!!.supportActionBar!!.hide()
getActivity()?.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
val soundEffects = SoundEffects(requireContext())
soundEffects.playSound(SoundEffects.backgroundMusic)
val outMetrics = DisplayMetrics()
getActivity()?.getWindow()?.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
window = activity?.getWindow()!!
window.attributes.width
window.attributes.height
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
val display = activity?.display
display?.getRealMetrics(outMetrics)
} else {
#Suppress("DEPRECATION")
val display = activity?.windowManager?.defaultDisplay
#Suppress("DEPRECATION")
display?.getMetrics(outMetrics)
}
size.y = outMetrics.heightPixels
size.x = outMetrics.widthPixels
backgroundMusic = MediaPlayer.create(requireContext(), R.raw.background_music)
backgroundMusic.isLooping = true
backgroundMusic.start()
val fragmentBinding = FragmentFullscreenSoloBinding.inflate(inflater, container, false)
binding = fragmentBinding
fragmentBinding.root
spaceView = SpaceView(requireContext(), size, this)
return spaceView
}
fun follow(){
findNavController().navigate(R.id.action_fullscreenFragmentSolo_to_gameoverFragment)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding?.soloFragment = this
}
override fun onResume() {
super.onResume()
spaceView?.resume()
}
fun stopFunction() {
spaceView?.stop()
}
override fun onPause() {
super.onPause()
backgroundMusic.release()
spaceView?.pause()
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
GameoverFragment:
open class GameoverFragment : Fragment() {
private var binding: GameoverFragmentBinding? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val fragmentBinding = GameoverFragmentBinding.inflate(inflater, container, false)
binding = fragmentBinding
return fragmentBinding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding?.gameoverFragment = this
}
fun Menu(){
findNavController().navigate(R.id.action_gameoverFragment_to_startFragment)
}
> override fun onDestroyView() {
> super.onDestroyView()
> binding = null }
Can you help me?
This exception is due to your code calling (through navigation) the LifecycleRegistry.addObserver from a thread other than the Main thread. You have to ensure that you call the navigation from the main thread.
Change to this in the follow() function
import android.os.Handler
import android.os.Looper
// ...
fun follow() {
Handler(Looper.getMainLooper()).post {
findNavController().navigate(R.id.action_fullscreenFragmentSolo_to_gameoverFragment)
}
}

How to solve view binding null pointer exception when activity restarts and fragment recreates

Anytime my MainActivity restarts because of changing of dark mode and i try to click i get nullpointer exception.
The error is below
I have a BaseFragment
lateinit var mContext:Context
lateinit var mActivity:Activity
var myId = ""
val firebaseMethods: FirebaseMethods by lazy { FirebaseMethods(requireActivity()) }
override fun onDestroy() {
super.onDestroy()
removeListeners()
}
override fun onAttach(context: Context) {
super.onAttach(context)
showLogI("onAttach")
}
override fun onDetach() {
super.onDetach()
showLogI("onDetach")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mContext = requireContext()
mActivity = requireActivity()
showLogI("onCreate")
if(getCurrentUser() != null){
myId = getCurrentUserId()
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?)
: View {
showLogI("onCreateView")
val view = setContentView(inflater, container, savedInstanceState)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView(view)
setListener()
initData()
}
protected abstract fun setContentView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?):View
protected abstract fun setListener()
protected abstract fun initData()
I also have a PostFragment
var posts:ArrayList<Post> = arrayListOf()
var pgPosts:ArrayList<Post> = arrayListOf()
var ids:ArrayList<String> = arrayListOf()
val keys:ArrayList<String> = arrayListOf()
var totalSize = 0
var query: Query? = null
var postAdapter:PostAdapter? = null
var counter = 0
var adUnit = ""
var adminId = ""
override fun onDestroy() {
super.onDestroy()
postAdapter?.removeListeners()
destroyAds()
}
private var _binding: FragmentPostBinding? = null
private val binding get() = _binding!!
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun setContentView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentPostBinding.inflate(inflater, container, false)
return binding.root
}
override fun setListener() {
}
override fun initData() {
getArgs()
toggleOrientation()
showProgress()
setAdapter()
val spannableString = "No Internet Connection. Retry".createSpan("Retry"){ spannableString, start, end ->
mContext.setSpan(spannableString, "click", start, end, R.color.green){readPosts()}
}
if (mContext.isConnectingToInternet()) readPosts() else hideProgressWithSpan(spannableString)
adUnit = mContext.getString(R.string.ads_unit_video)
firebaseMethods.getAdmin { admin->
adminId = admin.admin_id
//adUnit = admin.native_ads_unit
}
}
fun changeLayout(orientation:String){
this.orientation = orientation
toggleOrientation()
setAdapter()
}
fun toggleOrientation(){
if (orientation == "big") {
max = 5
binding.recyclerview.lm()
} else if (orientation == "small") {
max = 15
binding.recyclerview.lm("grid", 3)
}
}
I get this null pointer exception
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.wh, PID: 26862
java.lang.NullPointerException at com.wh.ui.fragment.post.PostFragment.getBinding(PostFragment.kt:101)
at com.wh.ui.fragment.post.PostFragment.toggleOrientation(PostFragment.kt:160)
at com.wh.ui.fragment.post.PostFragment.changeLayout(PostFragment.kt:154)
As #Tenfour04 has said , you're accessing the binding when the fragment has been detached. You need to first check if the fragment has been added like so
if(isAdded){
//do something with the binding
}
Thanks a lot. I finally found the solution. I was checking if state is null for my bottom navigation view fragments and if null using new fragment, if not finding fragmentbytag. I just guessed to create the fragment without checking state and it worked.

How do I pass the variables of an activity to the fragments of a BottomNavigationView?

I am very new to taking an android application and for a project I need a BottomNavigati but I cannot get my data that comes from the beginning of the session to pass to the main fragment
Activity:
val bundle1 = Bundle()
bundle1.putString("User",User)
bundle1.putString("Correo",Correo)
bundle1.putString("Region",Region)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController: NavController = navHostFragment.navController
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications
)
)
navHostFragment.arguments = bundle1
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
HOMEFRAGMEN:
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)
val textView: TextView = root.findViewById(R.id.textView4)
return root
}
}
There is no direct access to HomeFragment from MainActivity in your case. BottomNavigation uses nested navigation architecture pattern with nested graphs.
More details here: Passing argument(s) to a nested Navigation architecture component graph
But you can use alternative way to pass data from Activity to Fragment using context.
Step 1 - Describe HomeFragmentData model:
data class HomeFragmentData(
val value: String
)
Step 2 - Describe HomeFragment interface:
interface IHomeFragment {
fun getHomeFragmentData(): HomeFragmentData
}
Step 3 - Implement interface to your Activity:
class MainActivity : AppCompatActivity(), IHomeFragment {
override fun getHomeFragmentData(): HomeFragmentData {
return HomeFragmentData(
value = "Home Fragment data"
)
}
// Rest of your code
}
Step 4 - Call function getHomeFragmentData() from HomeFragment using context:
class HomeFragment : Fragment() {
private var interactionListener: IHomeFragment? = null
override fun onAttach(context: Context) {
super.onAttach(context)
when(context) {
is IHomeFragment -> {
interactionListener = context
}
else -> throw RuntimeException("$context has to implement IHomeFragment")
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
interactionListener?.getHomeFragmentData().let {
textView.text = it?.value
}
return root
}
}

Vertical Viewpager not working in kotlin android

I have been working on an app where were people can watch videos like tik tok. At first I made it with recyclerview and later on I realized that I should use Vertical Viewpager. Then I used Viewpager2 but I faced some problems so I replaced it with viewpager1. But still it is not working. I am doing this in my fragment. I want to play videos from firebase in Vertical viewpager using videoview.
In Viewpager_Adapter u can see that I have called one more layout there which is viewer_page but when I run my app I don't get that layout in my fragment
ViewpagerAdapter
class ViewpagerAdapter(var context: Context) : PagerAdapter() {
lateinit var inflater: LayoutInflater
var contentDTOs: ArrayList<ContentDTOs> = arrayListOf()
var contentUidList: ArrayList<String> = arrayListOf()
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object` as ConstraintLayout
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object`as ConstraintLayout)
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
inflater = context.getSystemService(container.context.toString())as LayoutInflater
val view =inflater.inflate(R.layout.viewer_page,container,false)
val exo : View? = view?.findViewById(R.id.videoviews)
val path = Uri.parse(contentDTOs[position].videourl)
val views = view.findViewById<VideoView>(R.id.videoviews)
views.setVideoURI(path)
views.requestFocus()
views.setOnPreparedListener {
views.start()
}
container.addView(view)
return view
}
override fun getCount(): Int {
return contentDTOs.size
}
}
Watch_video_fragment
#SuppressLint("ResourceAsColor")
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val fragmentview = inflater.inflate(R.layout.fragment_watch_video, container, false)
fragmentview.videofragment?.setOnClickListener {
var fragment = Watch_video()
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.frag, fragment)
?.commit()
}
fragmentview.memefragment?.setOnClickListener {
var fragment = DetailViewFragment()
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.frag, fragment)
?.commit()
}
firestore = FirebaseFirestore.getInstance()
uid = FirebaseAuth.getInstance().currentUser?.uid
fragmentview.videofragment?.setOnClickListener {
var fragment = Watch_video()
activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.frag, fragment)
?.commit()
}
//
fragmentview.vertical_viewpager.adapter = ViewpagerAdapter(requireContext())
fragmentview.vertical_viewpager.setPageTransformer(false
) { page, position ->
page.rotationY = position * -30 // animation style... change as you want..
}
Can u guys plz help me

Kotlin with Anko unknown resource and null reference

I Want to get Data from https://www.thesportsdb.com/api/v1/json/1/eventspastleague.php?id=4328
But I have error
java.lang.IllegalArgumentException: Parameter specified as non-null is
null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull,
parameter data at
com.yutra.jadwalbola.last_match.LastMatchFragment.showTeamList(Unknown
Source:21) at
com.yutra.jadwalbola.last_match.LastMatchPresenter$getTeamList$1$1.invoke(LastMatchPresenter.kt:21)
at
com.yutra.jadwalbola.last_match.LastMatchPresenter$getTeamList$1$1.invoke(LastMatchPresenter.kt:8)
this is my LastMatchDBApi
object LastMatchDBApi {
fun getMatch(): String {
return Uri.parse(BuildConfig.BASE_URL).buildUpon()
.appendPath("api")
.appendPath("v1")
.appendPath("json")
.appendPath(BuildConfig.TSDB_API_KEY)
.appendPath("eventspastleague.php")
.appendQueryParameter("id", "4328")
.build()
.toString()
}
}
this is my serialized
data class LastMatch(
#SerializedName("strEvent")
var eventName: String? = null
)
this is my presenter
class LastMatchPresenter(private val view: MainView,
private val apiRepository: ApiRepository,
private val gson: Gson) {
fun getTeamList() {
view.showLoading()
doAsync {
val data = gson.fromJson(apiRepository
.doRequest(LastMatchDBApi.getMatch()),
LastMatchResponse::class.java
)
uiThread {
view.hideLoading()
view.showTeamList(data.lastMatch)
}
}
}
}
this is my response
data class LastMatchResponse(
val lastMatch: List<LastMatch>
)
this is my fragment activity
class LastMatchFragment : Fragment(), MainView {
private lateinit var progressBar: ProgressBar
private lateinit var swipeRefresh: SwipeRefreshLayout
private var lastMatch: MutableList<LastMatch> = mutableListOf()
private lateinit var adapter: MainAdapter
private lateinit var listTeam: RecyclerView
private var key : String = "4328"
companion object {
fun newInstance(): LastMatchFragment {
return LastMatchFragment()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = UI {
linearLayout {
lparams (width = matchParent, height = wrapContent)
orientation = LinearLayout.VERTICAL
topPadding = dip(16)
leftPadding = dip(16)
rightPadding = dip(16)
// textView {
// text = "test image"
// }
relativeLayout{
lparams (width = matchParent, height = wrapContent)
listTeam = recyclerView {
lparams (width = matchParent, height = wrapContent)
layoutManager = LinearLayoutManager(ctx)
}
progressBar = progressBar {
}.lparams{
centerHorizontally()
}
}
}
}.view
adapter = MainAdapter(lastMatch)
listTeam.adapter = adapter
val request = ApiRepository()
val gson = Gson()
var presenter = LastMatchPresenter(this, request, gson)
presenter.getTeamList()
return view
}
override fun showLoading() {
progressBar.visible()
}
override fun hideLoading() {
progressBar.invisible()
}
override fun showTeamList(data: List<LastMatch>) {
lastMatch.clear()
lastMatch.addAll(data)
adapter.notifyDataSetChanged()
}
}
IF anyone have sourcode to get this data please help me
In below code you are passing list as null from LastMatchPresenter class
view.showTeamList(data.lastMatch)
By default all variables and parameters in Kotlin are non-null. If you want to pass null parameter to the method you should add ? to it's type, for example:
override fun showTeamList(data: List<LastMatch>?) {
lastMatch.clear()
lastMatch.addAll(data)
adapter.notifyDataSetChanged()
}

Resources