简体   繁体   中英

How to implement a dynamic list view inside fragment android studio in Kotlin

I have two fragments that share information with each other, in the first one I have an edit text and button widget. The second fragment is just a listview. When the user clicks the button, it displays whatever is in the edit text widget in the second fragment. So if the user enters the text study and clicks the button the second fragment will display

Study

If the user then enters the text eat and clicks the button, the second fragment will display Study Eat

I am having so issues with displaying the texts

So far this is what I have done

class FirstFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        viewModel = activity?.run { ViewModelProvider(this)[MyViewModel::class.java]
        } ?: throw Exception("Invalid Activity")

        val view = inflater.inflate(R.layout.one_fragment, container, false)

        val button = view.findViewById<Button>(R.id.vbutton)
        val value = view.findViewById<EditText>(R.id.textView)
        


        button.setOnClickListener {





        }



        return view;
    }
}
class SecondFragment : Fragment() {

    lateinit var viewModel: MyViewModel

    @SuppressLint("MissingInflatedId")
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        viewModel = activity?.run { ViewModelProvider(this)[MyViewModel::class.java]
        } ?: throw Exception("Invalid Activity")

        val view = inflater.inflate(R.layout.page3_fragment, container, false)
        val valueView = v.findViewById<TextView>(R.id.textView)
return view


The problem I am having is how to display the texts

If I undestand you correctly, you want to share data between fragments? If yes, you can do that with "shared" viewModel. For example:

class FirstFragment : Fragment() {
    private var _binding: FragmentFirstBinding? = null
    private val binding get() = _binding!!
    private val sharedViewModel by activityViewModels<SharedViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentFirstBinding.inflate(inflater, container, false)

        binding.buttonChangeFragment.setOnClickListener {
        /*
        You can change data here, or in navigateWithNavController() from 
        activity (You already have an instance of your viewModel in activity)
        */
            sharedViewModel.changeData(binding.myEditText.text.toString())
            if (requireActivity() is YourActivity)
                (requireActivity() as YourActivity).navigateWithNavController()
        }

        return binding.root
    }
}


class SecondFragment : Fragment() {
    private var _binding: FragmentSecondBinding? = null
    private val binding get() = _binding!!
    private val sharedViewModel by activityViewModels<SharedViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSecondBinding.inflate(inflater, container, false)

        binding.secondFragmentText.text = sharedViewModel.someData.value

        return binding.root
    }
}

and your activity:

class YourActivity: AppCompatActivity() {
    private lateinit var binding: YourActivityBinding
    private lateinit var appBarConfiguration: AppBarConfiguration
    private val sharedViewModel: SharedViewModel by lazy {
        ViewModelProvider(
            this
        )[SharedViewModel::class.java]
    }
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = YourActivityBinding.inflate(LayoutInflater.from(this))
        setContentView(binding.root)

        navController = this.findNavController(R.id.nav_host_fragment)
        appBarConfiguration = AppBarConfiguration(navController.graph)
    }

    /*
    This function is just for test
    */
    fun navigateWithNavController() {
        navController.navigate(R.id.secondFragment)
    }

    override fun onSupportNavigateUp(): Boolean {
        return NavigationUI.navigateUp(navController, appBarConfiguration)
    }
}

And your viewModel should look something like this:

class SharedViewModel : ViewModel() {
    private val _someData = MutableLiveData("")
    val someData: LiveData<String>
        get() = _someData

    fun changeData(newData: String?) {
        _someData.value = newData ?: _someData.value
    }
}

Your view model should have a backing list of the entered words. When a word is added, the list can be updated, and in turn you can update a LiveData that publishes the latest version of the list.

class MyViewModel: ViewModel() {
    private val backingEntryList = mutableListOf<String>()

    private val _entryListLiveData = MutableLiveData("")
    val entryListLiveData : LiveData<String> get() = _entryListLiveData 

    fun addEntry(word: String) {
        backingEntryList += word
        _entryListLiveData.value = backingEntryList.toList() // use toList() to to get a safe copy
    }
}

Your way of creating the shared view model is the hard way. The easy way is by using by activityViewModels() .

I also suggest using the Fragment constructor that takes a layout argument, and then setting things up in onViewCreated instead of onCreateView . It's less boilerplate code to accomplish the same thing.

In the first fragment, you can add words when the button's clicked:

class FirstFragment : Fragment(R.layout.one_fragment) {
    private val viewModel by activityViewModels<MyViewModel>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val button = view.findViewById<Button>(R.id.vbutton)
        val value = view.findViewById<EditText>(R.id.textView)

        button.setOnClickListener {
            viewModel.addEntry(value.text.toString())
        }
    }
}

In the second fragment, you observe the live data:

class SecondFragment : Fragment(R.layout.page3_fragment) {
    private val viewModel by activityViewModels<MyViewModel>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val valueView = view.findViewById<TextView>(R.id.textView)
        viewModel.entryListLiveData.observe(viewLifecycleOwner) { entryList ->
            valueView.text = entryList.joinToString(" ")
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM