How to remove first view pager item in kotlin? - android

I use View-Pager2 in my application that Which displays several same fragments. I also have a dialog fragment and inside it, I manage view pager items(add and remove items). Every fragment inside the view-pager has an id that saved in the SQLite database.
So, My problem is, When I remove the first item of view-pager, It does not delete and still remains but another item removed and when I launch the app again, I see the first item has been removed and everything is ok.
Main Activity Class:
class MainActivity : AppCompatActivity() {
private lateinit var databaseHelper: DatabaseHelper
private lateinit var myPagerAdapter: MyPagerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
databaseHelper = DatabaseHelper(this)
myPagerAdapter = MyPagerAdapter(supportFragmentManager, lifecycle)
view_pager.adapter = myPagerAdapter
if (databaseHelper.getCount().toInt() == 0) {
//red
databaseHelper.insertData(0, Color.argb(255, 244, 67, 54))
//blue
databaseHelper.insertData(1, Color.argb(255, 33, 150, 243))
//green
databaseHelper.insertData(2, Color.argb(255, 76, 175, 80))
}
btn_show.setOnClickListener {
val ft = supportFragmentManager.beginTransaction()
ft.add(FragmentTwo(), "Dialog")
ft.addToBackStack(null)
ft.commit()
}
}
private inner class MyPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(fragmentManager, lifecycle) {
override fun getItemCount(): Int {
return databaseHelper.getCount().toInt()
}
override fun createFragment(position: Int): Fragment {
return FragmentOne.newInstance(position)
}
}
fun setViewPagerPosition(position: Int) {
view_pager.currentItem = position
}
fun setViewPagerChanged() {
myPagerAdapter.notifyDataSetChanged()
}
}
FragmentOne class:
class FragmentOne : Fragment() {
companion object {
fun newInstance(position: Int): FragmentOne {
val fragment = FragmentOne()
val bundle = Bundle()
bundle.putInt("id", position)
fragment.arguments = bundle
return fragment
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_one, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val databaseHelper = DatabaseHelper(context)
val id = arguments?.getInt("id")
frame_frag1?.setBackgroundColor(databaseHelper.getColor(id))
}
}
FragmentTwo class (dialog fragment):
class FragmentTwo : DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val databaseHelper = DatabaseHelper(context)
btn_remove?.setOnClickListener {
(context as MainActivity).setViewPagerPosition(2)
databaseHelper.deleteData("0")
databaseHelper.updateRowsRemoveTab(id)
(context as MainActivity).setViewPagerChanged()
}
}
}
And its DatabaseHelper class:
class DatabaseHelper(context: Context?) : SQLiteOpenHelper(context, "tabs.db", null, 1) {
private val TBL_NAME: String = "tabs"
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL("CREATE TABLE $TBL_NAME (ID INTEGER , COLOR INTEGER)")
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
db?.execSQL("DROP TABLE IF EXISTS $TBL_NAME")
onCreate(db)
}
fun insertData(id: Int, color: Int) {
val db = this.writableDatabase
val cv = ContentValues()
cv.put("ID", id)
cv.put("COLOR", color)
db.insert(TBL_NAME, null, cv)
}
fun getColor(id: Int?): Int {
val db = this.readableDatabase
var color = 0
val cursor = db.rawQuery("select COLOR from $TBL_NAME where ID = $id", null)
if (cursor.moveToFirst())
do {
color = (cursor.getInt(0))
} while (cursor.moveToNext())
return color
}
fun updateRowsRemoveTab(id: Int) {
val db = this.writableDatabase
db.execSQL("update tabs set ID = ID-1 where ID > $id")
}
fun deleteData(id: String) {
val db = this.writableDatabase
db.delete(TBL_NAME, "ID = ?", arrayOf(id)).toLong()
}
fun getCount(): Long {
val db = this.readableDatabase
val count = DatabaseUtils.queryNumEntries(db, TBL_NAME)
db.close()
return count
}
}
Can you help me?

I do your do without viewpager2 and it ok. I copy your codes and just edit your view pager adapter to this:
private inner class MyPagerAdapter(fragmentManager: FragmentManager) :
FragmentPagerAdapter(fragmentManager) {
override fun getItem(position: Int): Fragment {
return FragmentOne.newInstance(position)
}
override fun getCount(): Int {
return databaseHelper.getCount().toInt()
}
override fun getItemPosition(`object`: Any): Int {
return PagerAdapter.POSITION_NONE
}
}
Dont forget to add PagerAdapter.POSITION_NONE to getItemPosition method.
This way is correct but I don't know how to do this with viewpager2.

Related

How to update layout contain after API is been called in PagerAdapter

I have created viewpager layout in which i am passing three different layout which need be update when any API is been called all three any time whether that page is been selected or not.
MainActivity.java
int[] layouts = new int[]{R.layout.one, R.layout.two, R.layout.three};
MyAdapter adapter = new MyAdapter(this, layouts);
MyAdapter.java
it is been extends to PagerAdapter
View view = layoutInflator.inflate(mLayouts[position], container, false);
container.addView(view);
How to initialize of all the id of different layout and how I can update the text or layout when API is been called.
Please try this way according to your requirement you can also create 3 childFragment with different layout and add them in list
class MyFragment : Fragment{
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return super.onCreateView(inflater, container, savedInstanceState)
initPager()
}
var fragmentAdapter: PagerAdapter? = null
fun initPager() {
fragmentAdapter = PagerAdapter(
childFragmentManager)
val fragment1 = ChildFragment("1")
fragmentAdapter!!.addFragment(fragment1,"title")
val fragment2 = ChildFragment("2")
fragmentAdapter!!.addFragment(fragment2,"title")
val fragment3 = ChildFragment("3")
fragmentAdapter!!.addFragment(fragment3,"title")
viewPager.adapter = fragmentAdapter
viewPager.offscreenPageLimit = 3
viewPager.addOnPageChangeListener(object :
ViewPager.OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
}
override fun onPageSelected(position: Int) {
// do this instead, assuming your adapter reference
// is named mAdapter:
for (page in childFragmentManager.fragments) {
val frag: Fragment = fragmentAdapter!!.getItem(position)
if (frag != null && frag is ChildFragment && page is ChildFragment) {
page.refresh()
}
}
}
override fun onPageScrollStateChanged(state: Int) {}
})
}
}
class PagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager) {
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
val activeFragment: List<Fragment>
get() = mFragmentList
override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}
override fun getCount(): Int {
return mFragmentList.size
}
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
override fun getPageTitle(position: Int): CharSequence? {
return mFragmentTitleList[position]
}
}
class ChildFragment : Fragment{
var type:String = ""
constructor(type:String){
this.type = type
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return super.onCreateView(inflater, container, savedInstanceState)
if(type.equals("")){
//TODO LAYOUT LOGIC here according to type validation
}else{
//TODO LAYOUT LOGIC here according to type validation
}
refresh()
}
fun refresh() {
//TODO CALL API and update your layoyt here
}
}

How can I add ListView in Fragment using TabLayout?

I am really new at Kotlin. I tried to make slidable pages using TabLayout. I have 3 different Fragments and I need to add ListView or RecyclerView on that fragments but in this point I can't figure out where is I have to add adapter of ListView. I add adapter class on fragment's Kotlin file but I can't connect that and fragment.(I think) I got an error which is ListView cannot be null so I can say about my adapter didn't working correctly. How can I solve it?
Here I add my codes:
My SecondFragment.kt code:
class SecondFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val listView = view!!.findViewById<ListView>(R.id.main_listview)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val listView = view!!.findViewById<ListView>(R.id.main_listview)
return inflater.inflate(R.layout.fragment_second, container, false)
}
private class MyCustomAdapter(context: Context): BaseAdapter(){
private val mContext : Context
private val names = arrayListOf<String>("Test Name", "Steve Jobs", "Tim Cook", "Kobe King")
init {
mContext = context
}
// BURADA KAC TANE ROW OLDUGUNUN SOYLER..
override fun getCount(): Int {
return names.size
}
override fun getItem(position: Int): Any {
return "Test String"
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
//val textView = TextView(mContext)
//textView.text = "Here my first row for list view.."
//return textView
val layoutInflater = LayoutInflater.from(mContext)
val rowMain = layoutInflater.inflate(R.layout.row_for_list, parent, false)
val nameTextView = rowMain.findViewById<TextView>(R.id.name_textView)
nameTextView.text = names.get(position)
val positionTextView = rowMain.findViewById<TextView>(R.id.position_textview)
positionTextView.text = "Row Number: $position"
return rowMain
}
}
}
Here my ViewPagerAdapter.kt file code:
class ViewPagerAdapter(supportFragmentManager: FragmentManager) : FragmentPagerAdapter(supportFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
override fun getCount(): Int {
return mFragmentList.size
}
override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}
override fun getPageTitle(position: Int): CharSequence? {
return mFragmentTitleList[position]
}
fun addFragment(fragment: Fragment, title: String){
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
}
And here my MainActivity.kt file code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setUpTabs()
}
private fun setUpTabs() {
val adapter = ViewPagerAdapter(supportFragmentManager)
adapter.addFragment(HomeFragment(), "Home")
adapter.addFragment(SecondFragment(), "Second")
adapter.addFragment(ThirdFragment(), "Third")
viewPager.adapter = adapter
tabs.setupWithViewPager(viewPager)
tabs.getTabAt(0)!!.setIcon(R.drawable.ic_baseline_account_box_24)
tabs.getTabAt(1)!!.setIcon(R.drawable.ic_baseline_add_ic_call_24)
tabs.getTabAt(2)!!.setIcon(R.drawable.ic_baseline_adb_24)
}
}
You have to set to instantiate the adapter and set it to the listView, I also explained some things in the comments.
class SecondFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//don't do this in onCreate, do it in onViewCreated or onCreateView
//val listView = view!!.findViewById<ListView>(R.id.main_listview)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val root = inflater.inflate(R.layout.fragment_second, container, false)
//you can set adapter here if you want, but i did it in onViewCreated
//return it
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
//get reference to ListView
val listView = root.findViewById<ListView>(R.id.main_listview)
//set adapter
listView.adapter = MyCustomAdapter(requireContext())
}
private class MyCustomAdapter(private val mContext: Context): BaseAdapter(){
//do initiation here as it needs to be done only once
private val layoutInflater: LayoutInflater = LayoutInflater.from(mContext)
private val names = arrayListOf<String>("Test Name", "Steve Jobs", "Tim Cook", "Kobe King")
// BURADA KAC TANE ROW OLDUGUNUN SOYLER..
override fun getCount(): Int {
return names.size
}
override fun getItem(position: Int): Any {
return "Test String"
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
//val textView = TextView(mContext)
//textView.text = "Here my first row for list view.."
//return textView
val rowMain = layoutInflater.inflate(R.layout.row_for_list, parent, false)
val nameTextView = rowMain.findViewById<TextView>(R.id.name_textView)
nameTextView.text = names.get(position)
val positionTextView = rowMain.findViewById<TextView>(R.id.position_textview)
positionTextView.text = "Row Number: $position"
return rowMain
}
}
}
Try this :
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view=inflater.inflate(R.layout.fragment_second, container, false)
val listView = view!!.findViewById<ListView>(R.id.main_listview)
val myListAdapter = MyCustomAdapter(container!!.context)
listView.adapter = myListAdapter
return view
}

ViewModel still displaying old data after dialog dismissed and parent fragment back to view

I'm still trying to wrap my head around working with viewmodels and a bit confused now that I also have a dialog and recyclerview items but will try to be as clear as I can here if I can get any help please.
I have a dialog with items that when one of them is selected and closed should return data to my calling fragment so the selected item is displayed under that view.
However, once the item is selected and the dialog dismissed, I don't see the new selected item as the one showing on the UI but still the old item instead. (When the fragment is first started it displays the item that is set as selected on my list. The selected value is hardcoded at first but updated when the item is clicked and I can see the update has taken place when I debug the viewmodel observer inside the onDismiss method for the dialog).
I'm a couple of hours on this and have tried a few different things such as calling the viewmodel inside onResume or onDismiss and changing the viewmodel to be initiated by by activityViewModels() as per this post but none of these have worked so far and I think I'm stuck at the moment. Below my most recent version of the code.
class CovidCheckInFragment : Fragment(R.layout.fragment_covid_check_in) {
var navController: NavController? = null
private val model: MainViewModel by activityViewModels()
#RequiresApi(Build.VERSION_CODES.M)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navController = Navigation.findNavController(view)
model.userMutableLiveData.observe(viewLifecycleOwner, Observer<Any?> { list ->
if (list != null)
(list as Iterable<*>).map {
if ((it as ModelDialogOption).selected == true) {
tvHeader.text = it.title
}
}
})
}
}
..
class MyDialogFragment : DialogFragment(), RecyclerDialogOptionsItem.AdapterListener {
private val viewModel: MainViewModel by activityViewModels()
private lateinit var adapter: GroupAdapter<GroupieViewHolder>
var selectedPosition = -1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.AppTheme_Dialog_Custom)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
rvOptions.layoutManager = LinearLayoutManager(activity)
adapter = GroupAdapter()
rvOptions.adapter = adapter
ivClose.setOnClickListener {
this.dismiss()
}
initViewModel()
}
private fun initViewModel() {
viewModel.userMutableLiveData.observe(this, Observer { list ->
for (i in list!!) {
adapter.add(
RecyclerDialogOptionsItem(
this#MyDialogFragment,
i,
this#MyDialogFragment
)
)
}
})
}
override fun onClickItem(position: Int) {
selectedPosition = position
adapter.notifyDataSetChanged()
Log.i("clicked", "position: $position")
}
}
..
class MainViewModel : ViewModel() {
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>?> = MutableLiveData()
init {
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
}
..
class RecyclerDialogOptionsItem(
private val fragment: MyDialogFragment,
private val modelDialogOption: ModelDialogOption,
private val adapterListener: AdapterListener
) : Item<GroupieViewHolder>() {
companion object {
var clickListener: AdapterListener? = null
}
override fun bind(viewHolder: GroupieViewHolder, position: Int) {
viewHolder.apply {
with(viewHolder.itemView) {
tvTitle.text = modelDialogOption.title
clickListener = adapterListener
if (fragment.selectedPosition == position) {
ivChecked.visible()
modelDialogOption.selected = true
} else {
ivChecked.invisible()
modelDialogOption.selected = false
}
itemView.setOnClickListener {
clickListener?.onClickItem(adapterPosition)
}
}
}
}
override fun getLayout() = R.layout.rv_options_item_row
interface AdapterListener {
fun onClickItem(position: Int)
}
}
Thank you very much.
Your main view model should be like this
class MainViewModel : ViewModel() {
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData = MutableLiveData<ArrayList<ModelDialogOption>>()
init {
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
fun updateItem(position:Int){
val itemToUpdate = list!!.get(position)
itemToUpdate.selected = !itemToUpdate.selected!!
list!![position] = itemToUpdate
}
fun flushItems(){
userMutableLiveData.value = list!!
}
}
Then from MyDialogFragment Should be like this.
class MyDialogFragment : DialogFragment(), RecyclerDialogOptionsItem.AdapterListener {
private val viewModel: MainViewModel by activityViewModels()
private lateinit var adapter: GroupAdapter<GroupieViewHolder>
var selectedPosition = -1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.AppTheme_Dialog_Custom)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
rvOptions.layoutManager = LinearLayoutManager(activity)
adapter = GroupAdapter()
rvOptions.adapter = adapter
ivClose.setOnClickListener {
this.dismiss()
}
initViewModel()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
viewModel.flushItems()
}
private fun initViewModel() {
viewModel.userMutableLiveData.observe(this, Observer { list ->
for (i in list!!) {
adapter.add(
RecyclerDialogOptionsItem(
this#MyDialogFragment,
i,
this#MyDialogFragment
)
)
}
})
}
override fun onClickItem(position: Int) {
selectedPosition = position
adapter.notifyDataSetChanged()
viewModel.updateItem(position)
Log.i("clicked", "position: $position")
}
}

RecyclerView doesn`t get elements from firestore KOTLIN firebase

i want to get recyclerview in my homefragment end set into elements from firestore firebase
my problem with get elements from firestore! maybe whos know how to search a problem because elements doesnt come frome firestore!
HomeFragment
class HomeFragment : Fragment() {
private val TAG = "HomeFragment"
private val firebaseRepository: FirebaseNoteRepo = FirebaseNoteRepo()
private var noteList: List<NotesModel> = ArrayList()
private val notesListAdapter: NotesListAdapterClass = NotesListAdapterClass(noteList)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
init(view)
}
private fun init(view: View) {
if(firebaseRepository.getUser() == null){
Log.d(TAG,"Error log user")
}else{ loadNotesData()}
note_list_recycler_view.layoutManager = LinearLayoutManager(context)
note_list_recycler_view.adapter = notesListAdapter
add_note_fab.setOnClickListener {
noteCreateDialog(view)
}
}
private fun loadNotesData() {
firebaseRepository.getNoteList().addOnCompleteListener {
if (it.isSuccessful){
noteList = it.result!!.toObjects(NotesModel::class.java)
notesListAdapter.notesListItem = noteList
notesListAdapter.notifyDataSetChanged()
}else{
Log.d(TAG,"Error: ${it.exception!!.message}")
}
}
}
my NotesModel
data class NotesModel(
val title: String = "",
val date: com.google.firebase.Timestamp? = null,
val post_type: Long = 0
)
my repository
FirebaseNoreRepo
class FirebaseNoteRepo {
private val firebaseAuth: FirebaseAuth = FirebaseAuth.getInstance()
private val firebaseFirestore: FirebaseFirestore = FirebaseFirestore.getInstance()
fun getUser(): FirebaseUser? {
return firebaseAuth.currentUser
}
fun getNoteList(): Task<QuerySnapshot> {
Log.d("HomeFragment"," ad "+ firebaseFirestore.collection("Notes").get().toString())
return firebaseFirestore
.collection("Notes")
.orderBy("title", Query.Direction.ASCENDING)
.get()
}
and my adapter
class NotesListAdapterClass (var notesListItem: List<NotesModel>):
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.note_layout,parent,false)
return ViewHolderNotes(view)
}
override fun getItemViewType(position: Int): Int {
return if (notesListItem[position].post_type == 1L){
POST_TYPE1
}else{
POST_TYPE1
}
}
override fun getItemCount(): Int {
Log.d("HomeFragment","notesListAdapter size : "+notesListItem.size)
return notesListItem.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (getItemViewType(position) == POST_TYPE1){
(holder as ViewHolderNotes).bind(notesListItem[position])
}
}
class ViewHolderNotes(itemView: View):RecyclerView.ViewHolder(itemView){
fun bind(notesModel: NotesModel){
itemView.note_title.text = notesModel.title
}
}
}
in my adapter i have Log.d he say me size of list of item ( is always equal 0), in firestore i have 2 elements. i dont understand why in log i have 0!
Database sceenshot

kotlin Android studio listView in Fragment

The listview shows in the first fragment properly, that is the first screen of my app.
but if I put the list view in another fragment that is not the first screen of the app. The app will shut down when i click other fragments.
Please kindly help to solve this issue.
here with my code of FourFragment:
class FourFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_four, container, false)
}
var adapter:TutorialAdapter? = null
var listOfTutorial = TutorialList().list
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = TutorialAdapter(context!!, mylist = listOfTutorial)
tutorialListView.adapter = adapter
}
fun openYoutubeLink(youtubeID: String) {
val intentApp = Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:" + youtubeID))
val intentBrowser = Intent(Intent.ACTION_VIEW, Uri.parse("http://www.youtube.com/watch?v=" + youtubeID))
try {
this.startActivity(intentApp)
} catch (ex: ActivityNotFoundException) {
this.startActivity(intentBrowser)
}
}
inner class TutorialAdapter : BaseAdapter {
var mylist=ArrayList<Tutorial>()
var context: Context?=null
constructor(context: Context, mylist:ArrayList<Tutorial>):super() {
this.context=context
this.mylist=mylist
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
val tutorialget = mylist[position]
var inflater = context!!.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
var myView = inflater.inflate(R.layout.tutorial_layout,null)
myView.title.text = tutorialget.name
myView.youtubeIcon.setImageResource(tutorialget.image!!)
myView.youtubeIcon.setOnClickListener {
openYoutubeLink(youtubeID = tutorialget.youtubeLink!!)
}
return myView
}
override fun getItem(position: Int): Any {
return mylist[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return mylist.size
}
}
}
Here with my code of MainActivity:
class MainActivity : AppCompatActivity() {
private var tabLayout: TabLayout? = null
var viewPager: ViewPager? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Action Bar
val actionBar = supportActionBar
actionBar!!.setDisplayShowHomeEnabled(true)
actionBar.setBackgroundDrawable(ColorDrawable(Color.parseColor("#00FFFFFF")))
actionBar.setIcon(R.drawable.title)
actionBar.setDisplayShowTitleEnabled(false)
viewPager = findViewById(R.id.viewpager) as ViewPager
setupViewPager(viewPager!!)
tabLayout = findViewById(R.id.tabs) as TabLayout
tabLayout!!.setupWithViewPager(viewPager)
val headerView = (getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
.inflate(R.layout.custom_tab, null, false)
val linearLayoutOne = headerView.findViewById(R.id.ll) as LinearLayout
val linearLayout2 = headerView.findViewById(R.id.ll2) as LinearLayout
val linearLayout3 = headerView.findViewById(R.id.ll3) as LinearLayout
val linearLayout4 = headerView.findViewById(R.id.ll4) as LinearLayout
tabLayout!!.getTabAt(0)!!.setCustomView(linearLayoutOne)
tabLayout!!.getTabAt(1)!!.setCustomView(linearLayout2)
tabLayout!!.getTabAt(2)!!.setCustomView(linearLayout3)
tabLayout!!.getTabAt(3)!!.setCustomView(linearLayout4)
}
private fun setupViewPager(viewPager: ViewPager) {
val adapter = ViewPagerAdapter(supportFragmentManager)
adapter.addFragment(OneFragment(), "ONE")
adapter.addFragment(TwoFragment(), "TWO")
adapter.addFragment(ThreeFragment(), "THREE")
adapter.addFragment(FourFragment(), "FOUR")
viewPager.adapter = adapter
}
internal inner class ViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager) {
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
override fun getItem(position: Int): Fragment {
return mFragmentList[position]
}
override fun getCount(): Int {
return mFragmentList.size
}
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
override fun getPageTitle(position: Int): CharSequence {
return mFragmentTitleList[position]
}
}
}
your ListView instance is null. You should instantiate tutorialListView inside onCreateView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view: View = inflater.inflate(R.layout.fragment_four, container, false)
tutorialListView = view.findViewById<ListView>(R.id.recycler_view)
return view
}

Categories

Resources