This is my first question on Stack Overflow, so apologies in advance if I'm asking in an improper way.
I'm trying to create a basic app in Kotlin, wherein I have a hamburger menu with some fragments in it. When the user clicks on the HomeFragment, I want to display a welcome message with his name (stored in a Shared Preferences object).
However, each time I click on the menu button to open the fragment, it crashes - even if I remove the whole username/shared prefs thing and just try to set some plain text.
Here is my HomeFragment.kt file:
package com.urmilshroff.kotlindemo
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_home.*
private const val ARG_PARAM1="param1"
private const val ARG_PARAM2="param2"
class HomeFragment:Fragment()
{
private var param1:String?=null
private var param2:String?=null
private var listener:OnFragmentInteractionListener?=null
override fun onCreate(savedInstanceState:Bundle?)
{
super.onCreate(savedInstanceState)
arguments?.let {
param1=it.getString(ARG_PARAM1)
param2=it.getString(ARG_PARAM2)
}
}
override fun onCreateView(inflater:LayoutInflater,container:ViewGroup?,
savedInstanceState:Bundle?):View?
{
super.onCreate(savedInstanceState)
val username=SharedPrefObj.getUsername(this.activity!!)
textViewHello.text="Hi there, $username!"
return inflater.inflate(R.layout.fragment_home,container,false)
}
fun onButtonPressed(uri:Uri)
{
listener?.onFragmentInteraction(uri)
}
override fun onAttach(context:Context)
{
super.onAttach(context)
if(context is OnFragmentInteractionListener)
{
listener=context
}
else
{
throw RuntimeException(context.toString()+" must implement OnFragmentInteractionListener")
}
}
override fun onDetach()
{
super.onDetach()
listener=null
}
interface OnFragmentInteractionListener
{
fun onFragmentInteraction(uri:Uri)
}
companion object
{
#JvmStatic
fun newInstance()=
HomeFragment().apply {
arguments=Bundle().apply {
putString(ARG_PARAM1,param1)
putString(ARG_PARAM2,param2)
}
}
}
}
My fragment_home.xml, just in case:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".HomeFragment">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textViewHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:fontFamily="monospace"
android:textAlignment="center"
android:textColor="#color/colorAccent"
android:textSize="30sp"
app:layout_constraintBottom_toTopOf="#+id/textViewDesc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.993" />
<TextView
android:id="#+id/textViewDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="240dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:fontFamily="monospace"
android:text="#string/text_view_desc"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
</FrameLayout>
Crash log:
09-17 00:19:24.968 25279-25279/com.urmilshroff.kotlindemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.urmilshroff.kotlindemo, PID: 25279
java.lang.IllegalStateException: textViewHello must not be null
at com.urmilshroff.kotlindemo.HomeFragment.onCreateView(HomeFragment.kt:37)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2346)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1428)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
It says that textViewHello must not be null, so I tried making it nullable yet it crashes. Not sure what's wrong. Any help is much appreciated, thanks!
textViewHello has not been initialized.
Initialise it like this:
val rootView = inflater.inflate(R.layout.fragment_home,container,false)
val textViewHello: TextView = rootView.findViewById(R.id.textViewHello) as TextView
Add the above line before setting text on textview
final onCreateView will look like this:
super.onCreate(savedInstanceState)
val rootView = inflater.inflate(R.layout.fragment_home,container,false)
val username=SharedPrefObj.getUsername(this.activity!!)
val textViewHello: TextView = rootView.findViewById(R.id.textViewHello) as TextView
textViewHello.text="Hi there, $username!"
return rootView;
You are using Kotlin Android Extentions in your project, so no need to call findViewById method anymore.
All you need to do is change your code to:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
super.onCreate(savedInstanceState)
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val username = SharedPrefObj.getUsername(this.activity!!)
textViewHello.text = "Hi there, $username!"
}
put below line in onViewCreated method. You need to override that method.
textViewHello.text="Hi there, $username!"
this will set the textview after it has been initiated in onCreateView
You need use it in onViewCreated.
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.qr_my_fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
init()
}
private fun init() {
setQRCode()
initToolbar()
clickEvents()
}
You are trying to call method setText, but your TextView object actually is null. You need to initialize.
Before set text, you should make some step.
1. Inflate view in variable
val view = inflater.inflate(R.layout.fragment_home,container,false)
2. Find and connect xml object with class variable
val textView: TextView = view.findViewById(R.id.textViewHello)
3. Now, you can call setText
textView.setText("Example text")
Just modify your onCreateView method
val view = inflater.inflate(R.layout.fragment_home,container,false)
val textView: TextView = view.findViewById(R.id.textViewHello)
textView.setText("Example text")
Related
I am pretty new to Android development, so please go easy on me, but I have hit a dead-end trying to figure out why I can't add an event listener to any buttons within a fragment. What I am trying to do is I have a Fragment that will serve as the general landing page for my app that has a series of buttons the user should be able to click on that will navigate them to the other pages of the app. All the buttons are there, but I can't get them to do anything. The println statement that is supposed to print out the the id of the current button does work, so the code is entering the switch case, but the setOnClickListener isn't behaving the way I would expect. Here is what I have currently for the code of the Fragment class I am working on (please note there is a closing bracket to end the class I just couldn't get it in the code styling for some reason):
class HomeFragment : Fragment() {
private val buttonFragments = listOf("recipes", "budget", "inventory", "customers",
"reports")
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)
for(button in buttonFragments) {
var currentHomeButton: View
when(button) {
"recipes" -> {
currentHomeButton = view.findViewById(R.id.button_recipes)
println(currentHomeButton.id)
currentHomeButton.setOnClickListener { println("Hello") }
}
}
}
}
Here is what I have tried:
The implementation you currently are seeing
Implementing View.OnClickListener and overriding the onClick function
trying to override the onClick function from within the setOnClickListener call
I hope this enough to go off of, but I can share more if needed.
UPDATE
After doing some more exploration, I think I better understand why my issue is occurring, but still can't find how to fix it. The HomeFragment is comprised of a series of custom buttons I have created called HomeButton. HomeButton is made up of a MaterialButton with a bunch of specific styling done to it. When I attach the setOnClick to the id of the material button, it works, but when trying to attach it to my custom component, it doesn't.
So after a good deal more research and trying out different solutions, I have figured out what the problem is and fixed it. The problem is that I am trying to attach a setOnClickListener on a custom view component I made. Because of this, the setOnClickListener gets attached to nothing (or at least nothing useful), because the function doesn't know how to work with a custom view component. To solve this, I implemented the following code in the HomeButton.kt custom view file:
private var listener: OnClickListener? = null
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_UP) {
if (listener != null) listener!!.onClick(this)
}
return super.dispatchTouchEvent(event)
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_UP &&
(event.keyCode == KeyEvent.KEYCODE_DPAD_CENTER ||
event.keyCode == KeyEvent.KEYCODE_ENTER)) {
if (listener != null) listener!!.onClick(this)
}
return super.dispatchKeyEvent(event)
}
override fun setOnClickListener(listener: OnClickListener?) {
this.listener = listener
}
This allows for the setOnClickListener to be used on the HomeButton custom view component. Then back in the HomeFragment.kt fragment file, this was the code I implemented and it worked with no problems:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
for(button in buttonFragments) {
var currentHomeButton: HomeButton
when(button) {
"recipes" -> {
currentHomeButton = view.findViewById(R.id.button_recipes)
currentHomeButton.setOnClickListener { utils.replaceFragment(
RecipesListFragment(), currentHomeButton.getText()) }
}
"budget" -> {
currentHomeButton = view.findViewById(R.id.button_budget)
currentHomeButton.setOnClickListener { utils.replaceFragment(
BudgetListFragment(), currentHomeButton.getText()) }
}
...
}
}
Hope this can help someone in the future
You're using standard output (println(...) function), which is not being used in Android apps.
Meaning, your click listener works but the code inside is useless unless you execute it manually on your development machine (with main function).
Learn how to use write logs using LogCat
Suppose we have a Fragment called (TestFragment)
Its layout :
fragment_testfragment.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presintation.TestFragment">
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="xxxxxxxxx"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.257" />
<Button
android:id="#+id/b1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="b1"
app:layout_constraintBottom_toTopOf="#+id/b2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/b2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="b2"
app:layout_constraintBottom_toTopOf="#+id/b3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/b3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="b3"
app:layout_constraintBottom_toTopOf="#+id/b4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/b4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="228dp"
android:text="b4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
to init 4 buttons (b1,b2,b3,b4) and change the text with the name of the clicked button
the code in the fragment class :
TestFragment.kt:
package com.mostafan3ma.android.hilttesting.presintation
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import com.mostafan3ma.android.hilttesting.R
import kotlin.math.log
class TestFragment : Fragment() {
private val TAG = "TestFragment"
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_testfragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.b1).setOnClickListener {
Log.d(TAG, "onViewCreated: b1 clicked")
Toast.makeText(context, "b1 clicked", Toast.LENGTH_SHORT).show()
view.findViewById<TextView>(R.id.txt).text = "b1"
}
view.findViewById<Button>(R.id.b2).setOnClickListener {
Log.d(TAG, "onViewCreated: b2 clicked")
Toast.makeText(context, "b2 clicked", Toast.LENGTH_SHORT).show()
view.findViewById<TextView>(R.id.txt).text = "b2"
}
view.findViewById<Button>(R.id.b3).setOnClickListener {
Log.d(TAG, "onViewCreated: b3 clicked")
Toast.makeText(context, "b3 clicked", Toast.LENGTH_SHORT).show()
view.findViewById<TextView>(R.id.txt).text = "b3"
}
view.findViewById<Button>(R.id.b4).setOnClickListener {
Log.d(TAG, "onViewCreated: b4 clicked")
Toast.makeText(context, "b4 clicked", Toast.LENGTH_SHORT).show()
view.findViewById<TextView>(R.id.txt).text = "b4"
}
}
}
The spinner just doesn't work, I tried different versions of the code, but it didn't work in any of them
Can anyone help solve this problem?
TransferFragment.kt
package com.example.hotel2.transfer
class TransferFragment : Fragment(){
private var _binding: FragmentTransferBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentTransferBinding.inflate(inflater, container, false)
val view = binding.root
return view
val transfers = arrayOf<String>("Flowers", "Candies")
val adapter: ArrayAdapter<String> =
ArrayAdapter<String>(activity?.applicationContext!!, android.R.layout.simple_spinner_item, transfers)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
val spinner = binding.spinner
spinner.adapter = adapter
spinner.prompt = "Title"
spinner.setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?, view: View?,
position: Int, id: Long
) {
}
override fun onNothingSelected(arg0: AdapterView<*>?) {}
})
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
fragment_transfer.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".transfer.TransferFragment">
<Spinner
android:id="#+id/spinner"
android:layout_width="200dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="300dp"
android:layout_marginStart="50dp"></Spinner>
</androidx.constraintlayout.widget.ConstraintLayout>
According to my guess, the problem is in activity?.applicationContext!!, but I do not understand how to solve it.
In onCreateView() you have this statement as the 4th statement in the method:
return view
All the code after this statement doesn't get executed.
Interestingly enough, your IDE (Android Studio or whatever) should tell you that!
I have a custom ConstraintLayout Myword. when I set the visibility of myword1 to GONE inside kotlin fun doOnLayout, it becomes invisible but myword2 doesn't move down.
But if I set its visibility to GONE in XML or outside doOnLayout, it works as intended.
<learnprogramming.academy.relaf.Myword
android:id="#+id/myword1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<learnprogramming.academy.relaf.Myword
android:id="#+id/myword2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="#id/myword1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
Source code:
lateinit var bannerword : MutableList<Myword>
lateinit var swippon : ConstraintLayout
fun updatewords{
swippon.doOnLayout {
if (swippon.height>1000) bannerword[0].visibility = View.GONE}
class PhrasesFragment: Fragment() {
companion object {
fun newInstance(): PhrasesFragment {
return PhrasesFragment()
}
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.inglesa_screen, container, false) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bannerword=mutableListOf(myword1,myword2)
swippon=parent
updatewords()
}
}
doOnLayout function when layout is laid out calculates parent Layout height and eventually removes myword1. I actually solved changing doOnLayout with Handler(Looper.getMainLooper()).post{} but is wrong with doOnLayout? How should i have used it in the correct way?
Do fragment need a very precise way of handling the texts that are set in the xml of the fragment ?
I had two times very similar problems : text written in xml cannot be updated properly.
Here is my first fragment. I previously had a foolish text written in the xml for the textview 'msg2ndfragment'. The issue I had was that during the onViewCreated, the text sent by the new Activity to the text would overlap the foolish text written in the Xml.
So I removed the foolish text, and now it is fine. (I could update thee text three times in a row it would work as long as the text was not initially defined in the xml),
class SecondFragment : Fragment() {
//Passer par new instance pour créé le fragment en lui donnant le nom à afficher
companion object {
fun newInstance(title: String?): SecondFragment {
val fragmentSecond = SecondFragment()
val args = Bundle()
args.putString(MainActivity.MESSAGE_SECOND_ACTIVITE, title)
fragmentSecond.arguments = args
return fragmentSecond
}
}
private lateinit var viewModel: SecondViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.second_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(SecondViewModel::class.java)
val message = arguments!!.getString(MainActivity.MESSAGE_SECOND_ACTIVITE, "")
val aries = view?.findViewById<TextView>(R.id.msg2ndfragment);
aries?.text = message
}
}
But now, I have a very similar issue: in a different fragment in another activity I have an editText with a hint. I want to make the hint disappear. Same issue : if the hint is written in the Xml : any text written by the user will only overlap the old text. If I initially define the hint dynamically, the hint disappears when the user starts writing.
class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.main_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
val aries = view?.findViewById<Button>(R.id.btnGo2ndActivity);
aries?.setOnClickListener { onGoSecondFragmentClick(it) }
Log.d("p1", "p1");
//Faire disparaitre le int au touch car cela ne se fait pas automatiquement
val edTxtTo2nd = view?.findViewById<EditText>(R.id.edt2ndActEditText)
edTxtTo2nd?.hint = "a"
Log.d("pouf", "pouf");
/*val edTxtTo2nd = view?.findViewById<EditText>(R.id.edt2ndActEditText)
edTxtTo2nd?.setOnClickListener(View.OnClickListener { v ->
edTxtTo2nd?.setHint("")
}) */
}
private var listener: onMvmtClickListener? = null
public interface onMvmtClickListener {
fun onNextActivityClick(name1: String)
}
// Store the listener (activity) that will have events fired once the fragment is attached
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is onMvmtClickListener) {
listener = context as onMvmtClickListener
} else {
throw ClassCastException(
"$context must implement nMvmtClickListener"
)
}
}
fun onGoSecondFragmentClick(v: View?) {
val nom = view?.findViewById<EditText>(R.id.edt2ndActEditText);
listener?.onNextActivityClick(nom?.text.toString())
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainFragment">
<TextView
android:id="#+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btnGo2ndActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:text="#string/go_to_2nd_act"
app:layout_constraintTop_toBottomOf="#+id/edt2ndActEditText"
tools:layout_editor_absoluteX="111dp"
tools:ignore="MissingConstraints" />
<EditText
android:id="#+id/edt2ndActEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="35dp"
android:layout_marginBottom="21dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintBottom_toTopOf="#+id/btnGo2ndActivity"
app:layout_constraintTop_toTopOf="#+id/message"
tools:layout_editor_absoluteX="95dp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
Edit : here are the main_activity kotelin and xml
class MainActivity : AppCompatActivity(), MainFragment.onMvmtClickListener {
companion object{
const val MESSAGE_SECOND_ACTIVITE = "Message.s
econd.activite"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow()
}
}
override fun onNextActivityClick(name1: String) {
var intent = Intent(this, SecondActivity::class.java)
intent.putExtra(MESSAGE_SECOND_ACTIVITE, name1)
startActivity(intent)
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id
/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<fragment
android:id="#+id/fragment"
android:name="com.example.myapplication.ui.main.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Using this workaround to define any text or hint feels wrong to me. How can I define them in the Xml of the fragment without having this overlap issue ?
Thank you in advance for any help.
I am attempting to adapt an ArrayList to an AutoCompleteTextView in a Fragment. I have had this working on another program, where I am applying the adapter in the MainActivity.
The error I am getting is:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.AutoCompleteTextView.setAdapter(android.widget.ListAdapter)' on a null object reference
My Fragment code - newFlightFrament.kt:
package com.android.joncb.flightlogbook
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.widget.ArrayAdapter
import com.android.joncb.flightlogbook.ExtFunctions.CreateList
import com.android.joncb.flightlogbook.dto.AirlineDTO
import com.google.gson.GsonBuilder
import kotlinx.android.synthetic.main.fragment_new_flight.*
private const val ARG_PARAM1 = "airlines"
class newFlightFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var airlineNameOnly = ArrayList<String>()
private var airlineFSCodeOnly = ArrayList<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
// Log.e("args", param1)
println(param1)
val gson = GsonBuilder().create()
val tempList :List<AirlineDTO> = gson.fromJson(param1,Array<AirlineDTO>::class.java).toList()
val airlines :ArrayList<AirlineDTO> = arrayListOf(AirlineDTO())
airlines.addAll(tempList)
airlineNameOnly = CreateList(airlines, "airlineName")!!
airlineFSCodeOnly = CreateList(airlines, "FS")!!
}
// val adapter = context?.let {
// ArrayAdapter<String>(
// it,
// android.R.layout.simple_list_item_1,
// airlineNameOnly
// )
// }
val adapter = ArrayAdapter<String>(requireActivity().baseContext,android.R.layout.simple_list_item_1,airlineNameOnly)
actxtAirlineName.setAdapter(adapter)
}
}
My Fragment XML - fragment_new_flight.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
tools:context=".newFlightFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/lblNewFlightInstruction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="#dimen/abPadding"
android:text="#string/lblNewFltInstr"
android:textSize="#dimen/medFont"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/abPadding"
android:paddingVertical="8dp"
android:text="#string/airline_name"
android:textSize="#dimen/medFont"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/lblNewFlightInstruction" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/abPadding"
android:paddingVertical="8dp"
android:text="#string/fsCode"
android:textSize="#dimen/medFont"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/actxtAirlineName" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/abPadding"
android:paddingVertical="8dp"
android:text="#string/fltNumber"
android:textSize="#dimen/medFont"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/etxtFSCode" />
<AutoCompleteTextView
android:id="#+id/actxtAirlineName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="#string/airline_name"
android:paddingStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/textView3"
app:layout_constraintTop_toTopOf="#+id/textView" />
.
.
.
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
I am getting the error when I setAdapter:
actxtAirlineName.setAdapter(adapter)
Note in my commented out section above this call I have tried another approach, which results in the same error.
I can confirm that the ArrayList airlineNameOnly is populated correctly.
Any ideas are good ideas.
Thanks.
You forget override onCreateView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_new_flight, container, false)
}
Change onCreate to onViewCreated, when onCreate call view doesn't inflate
I cannot see where you inflated your fragment's view. Perhaps there's the issue?
Change your code according to mine
First include this
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout. fragment_new_flight, container, false)
}
arguments?.let {
param1 = it.getString(ARG_PARAM1)
// Log.e("args", param1)
println(param1)
val gson = GsonBuilder().create()
val tempList :List<AirlineDTO> = gson.fromJson(param1,Array<AirlineDTO>::class.java).toList()
val airlines :ArrayList<AirlineDTO> = arrayListOf(AirlineDTO())
airlines.addAll(tempList)
airlineNameOnly = CreateList(airlines, "airlineName")!!
airlineFSCodeOnly = CreateList(airlines, "FS")!!
// val adapter = context?.let {
// ArrayAdapter<String>(
// it,
// android.R.layout.simple_list_item_1,
// airlineNameOnly
// )
// }
val adapter = ArrayAdapter<String>(requireActivity().baseContext,android.R.layout.simple_list_item_1,airlineNameOnly)
actxtAirlineName.setAdapter(adapter)
}
}
Hope it will work Thankew! Happy coding!