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!
Related
Hi I have an simple app with Bottom Navigation Activity. In Home Fragment I have a Button called Fruits. It opens a PopupWindow. In the popup is a RecyclerView with 4 Buttons(fruits names).
I want, when I press on a Button in the PopupWindow, to change the name of Button(called Fruits) form home_fragment, in whatever fruit was chosen.
HomeFragment:
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.Fruits.setOnClickListener {
show_popup(requireContext(), view, R.layout.fruits_popup)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
fun show_popup(c: Context, v: View, l: Int){
val popup_window = PopupWindow(c)
val inflater = layoutInflater.inflate(l, null)
val recyclerView: RecyclerView = inflater.findViewById(R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.adapter = FruitsAdapter()
popup_window.contentView = inflater
popup_window.isFocusable = true
popup_window.isOutsideTouchable = true
popup_window.showAtLocation(v, Gravity.CENTER, 0, 0)
}
}
FruitsAdapter:
class FruitsAdapter : RecyclerView.Adapter<FruitsAdapter.FruitsViewHolder>() {
private val list = listOf<String>("Banana", "Orange", "Apple", "Watermelon")
class FruitsViewHolder(val view: View): RecyclerView.ViewHolder(view) {
val button = view.findViewById<Button>(R.id.fruit)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitsViewHolder {
val layout = LayoutInflater.from(parent.context).inflate(R.layout.fruit, parent, false)
return FruitsViewHolder(layout)
}
override fun onBindViewHolder(holder: FruitsViewHolder, position: Int) {
val item = list.get(position)
holder.button.text = item.toString()
}
override fun getItemCount(): Int {
return list.size
}
}
fragment_gome.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=".ui.home.HomeFragment">
<Button
android:id="#+id/Fruits"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fruits"
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.254" />
</androidx.constraintlayout.widget.ConstraintLayout>
fruits_popup.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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recycler_view"/>
</FrameLayout>
fruit.xml
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fruit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:padding="8dp" />
Try to google with keyword 'callback' bro
I have simple DialogWindow
XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="150dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<fragment
android:id="#+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/navigation"/>
</LinearLayout>
Code:
class DialogWindowBuyingStock(context: Context, private val viewModel: MainViewModel, private val stock: Stock) : AppCompatDialog(context) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.buy_stock_dialogwindow)
}
}
In which i have some fragments for example the Main one:
class MainFragment : Fragment() {
private var _binding: MainFragmentBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val homeViewModel =
ViewModelProvider(this)[MainFragmentViewModel::class.java]
_binding = MainFragmentBinding.inflate(inflater, container, false)
val root: View = binding.root
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
main_buy_button.setOnClickListener {
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_buyFragment)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
It works perfectly for the first time i start Dialog Window, but when i close it and start again, i got this llegalArgumentException: Binary XML file line #20: Duplicate id 0x7f080136, tag null, or parent id 0xffffffff with another fragment for androidx.navigation.fragment.NavHostFragment
How can i fix that?
i have the xml with recyclerview, id = list_chat
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".ui.chats.ChatsFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list_chat"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
my Fragment where will be recyclerview with function uploadList which put data in my array for recyclerView
class ChatsFragment : Fragment() {
var list: MutableList<Chat> = ArrayList()
lateinit var adapter: ChatListAdapter
lateinit var manager: RecyclerView.LayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
uploadList()
Log.e("TAG", list.toString())
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view: View = inflater.inflate(R.layout.fragment_chats, container, false)
uploadList()
manager = LinearLayoutManager(activity)
list_chat.layoutManager = manager
adapter = ChatListAdapter(list)
list_chat.adapter = adapter
return view
}
private fun uploadList(){
list.add(Chat("11111", "11111"))
list.add(Chat("11222221", "133311"))
list.add(Chat("1122221", "114444411"))
list.add(Chat("112222211", "5555555"))
}
}
xml with item for list. ImageView is no matter for now. Need only two textView
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:id="#+id/item_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/chatImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/ic_launcher"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="5sp">
<TextView
android:id="#+id/nameChat"
android:text="2222222222222"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/infoChat"
android:text="11111111"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
</layout>
and my custom Adapter
class ChatListAdapter(private val myDataset: MutableList<Chat>) :RecyclerView.Adapter<ChatListAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
.inflate(R.layout.item_list, parent, false)
return ViewHolder(layoutInflater)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(myDataset[position])
}
override fun getItemCount() = myDataset.size
class ViewHolder(v: View) : RecyclerView.ViewHolder(v){
private val nameChat: TextView = itemView.findViewById(R.id.nameChat)
private val infoChat: TextView = itemView.findViewById(R.id.infoChat)
fun bind(chat: Chat){
nameChat.text = chat.name
infoChat.text = chat.info
}
}
}
and i catch java.lang.IllegalStateException: list_chat must not be null here list_chat.layoutManager = manager
help me with it, i have list_chat only in fragment_chats, so it is right recyclerview.
Because help me pls, I dont know what is the problem
Initialize layout manager and adapter in onViewCreated() Method
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
uploadList()
manager = LinearLayoutManager(activity)
list_chat.layoutManager = manager
adapter = ChatListAdapter(list)
list_chat.adapter = adapter
})
Are you using kotlinx.android.synthetic to find your views? If so, these are not valid until after onCreateView() returns, and so you cannot use them within onCreateView().
Move your code to onViewCreated(), or switch to manually calling view.findViewById() from inside onCreateView().
Approach 1 :
Create a recyclerview object :
val rv = view.findViewById(your rv id)
and assign the layout manager and adapter to it.
Approach 2 :
In your layout file, in recyclerview add this line :
<androidx.recyclerview.widget.RecyclerView
<!-- your default lines -->
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
/>
and assign the adapter in onViewCreated method.
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.
After rotation, one old page is displayed, followed by new pages.
Before rotation 1.
After rotation 2.
Layout with ViewPager:
<RelativeLayout ...
<androidx.viewpager.widget.ViewPager
android:id="#+id/pager"
android:overScrollMode="never"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="10dp"
android:layout_height="match_parent"
android:layout_width="match_parent">
</RelativeLayout>
Fragment with this layout:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = inflater.inflate(layoutId(), container, false)
view.findViewById<ViewPager>(R.id.pager).adapter = TextPagerAdapter(activity!!.supportFragmentManager, listOf())
return view
}
TextPagerAdapter:
override fun getItem(position: Int): Fragment = PageFragment.newInstance("sssssss ssss $position")
override fun getCount() = 5//pageText.size
}
PageFragment:
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {
val view = inflater.inflate(layoutId(), container, false)
view.findViewById<TextView>(R.id.page_content_textView).text = arguments!!.getCharSequence(PAGE_TEXT)
return view
}
I forgot to check if the content fragment is already created.
The solution is to check if the savedInstanceState == null. And create new fragment if that condition is true.
In MyActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(savedInstanceState == null) this.supportFragmentManager.beginTransaction()
.add(containerViewId, CollectionDemoFragment()).commit()
}