class ProfileFragment : Fragment() {
private lateinit var binding : FragmentProfileBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentProfileBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.imgProfileSetting.setOnClickListener {
Toast.makeText(context,"t",Toast.LENGTH_LONG).show()
}
logcat :: java.lang.NullPointerException: view.findViewById(R.id.imgProfileSetting) must not be null
}
}
Related
I created a popup window with rounded corners in a fragment but when I open it I can see a dark background behind the popup. Can you tell how to delete it or make ir transparent?
I'm using kotlin.
This is my fragment code (the activity with an image that opens the popup on click):
`
class ProfileFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val bpMore: ImageView = view.findViewById(R.id.ic_bp_more)
bpMore.setOnClickListener {
val showPopUp = BadgesPopUpFragment()
showPopUp.show((activity as AppCompatActivity).supportFragmentManager, "showPopUp")
}
}
`
And this is my popup fragment code (popup window):
`
class BadgesPopUpFragment : DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_badges_pop_up, container, false)
}
}
`
I'm trying to use the searchView widget in a fragment. I can't find a way to do it. It's easier to implement a searchView using an Activity but I have no clue how to do implement it in a fragment in Kotlin. I tried this way but doesn't seem to work ( only works in an activity). I'm a beginner in Android and would really appreciate some help here, i've been struggling for a couple of days rn.
class Homepage : Fragment() {
private var layoutManager : RecyclerView.LayoutManager? = null
private var _binding : FragmentHomepageBinding? = null
private val binding get() = _binding!!
private val shoe = DataSource.shoes
val arrayList = ArrayList<Shoe>()
val displayList = ArrayList<Shoe>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentHomepageBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val myAdapter = ShoeAdapter(displayList)
layoutManager = GridLayoutManager(this.context,2)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = myAdapter
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.main_menu,menu)
val menuItem = menu.findItem(R.id.search)
val searchView = menuItem.actionView as SearchView
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
if(newText!!.isNotEmpty()){
displayList.clear()
val search = newText.lowercase(Locale.getDefault())
arrayList.forEach {
if(it.name.lowercase(Locale.getDefault()).contains(search)){
displayList.add(it)
}
}
recyclerView.adapter!!.notifyDataSetChanged()
}
else{
displayList.clear()
displayList.addAll(arrayList)
recyclerView.adapter!!.notifyDataSetChanged()
}
return true
}
})
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return super.onOptionsItemSelected(item)
}
}```
I used it as below before and it was working properly.
class BooksFragment : Fragment(), SearchView.OnQueryTextListener {
private lateinit var binding: FragmentBooksBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentBooksBinding.inflate(inflater, container, false)
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_books, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.toolbar_menu,menu)
val item = menu.findItem(R.id.search_book)
val searchView = item.actionView as SearchView
searchView.setOnQueryTextListener(this)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onQueryTextSubmit(query: String): Boolean {
// search button submit
return true
}
override fun onQueryTextChange(newText: String): Boolean {
// search text changed
return true
}
I am a novice in Android development. I am currently working in fragments. So basically I am having two fragments each have their own Edittext and buttons. On back press between fragments works fine but when using the button to move to the next fragment the second fragment fails to hold the edit text value. I tried OnSavedInstance it doesn't help me.
FirstFragment.kt
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? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_first, container, false)
view.findViewById<Button>(R.id.btn1).setOnClickListener {
ediText1 = view.findViewById<EditText>(R.id.et1).text.toString()
Toast.makeText(activity?.baseContext,ediText1,Toast.LENGTH_SHORT).show()
Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment)
}
return view
}
SecondFragment.kt
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? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_second, container, false)
view.findViewById<Button>(R.id.btn2).setOnClickListener {
ediText2 = view.findViewById<EditText>(R.id.et2).text.toString()
Toast.makeText(activity?.baseContext,ediText2, Toast.LENGTH_SHORT).show()
Navigation.findNavController(view).navigate(R.id.action_secondFragment_to_thirdFragment) }
return view
}
There are many ways to retain the values, most easy is to use ViewModel , since you are using Navigation Components , ViewModel can be scoped to navGraph , see this
This is my Code for CallFragment.kt , when i click on btnSetupVideoCall nothing happens whereas i should be going to different activity.
class CallFragment : Fragment() {
private var param1: String? = null
private var param2: String? = null
private lateinit var binding: FragmentCallBinding
companion object {
#JvmStatic
fun newInstance(param1: String, param2: String) =
CallFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_call, container, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentCallBinding.inflate(layoutInflater)
binding.btnSetupVideoCall.setOnClickListener{
(activity as MainActivity?)?.let {
val intent = Intent(it, One_to_One_VC::class.java)
it.startActivity(intent)
}
}
}
}
And this is how i made fragments in mainactivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
val callFragment = CallFragment()
val chatFragment = ChatFragment()
makeCurrentFragment(callFragment)
binding.btmNvg.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.ic_call -> makeCurrentFragment(callFragment)
R.id.ic_chat -> makeCurrentFragment(chatFragment)
else -> makeCurrentFragment(callFragment)
}
true
}
}
override fun onBackPressed() {
if(binding.btmNvg.selectedItemId == R.id.ic_call){
super.onBackPressed()
finish()
}else{
makeCurrentFragment(CallFragment())
}
}
private fun makeCurrentFragment(fragment: Fragment) =
supportFragmentManager.beginTransaction().apply {
replace(R.id.fl_wrapper , fragment)
commit()
}
}
Logcat when i click the button
The only option left for me is to make another UI since it is starting of the project only but help would be really appreciated
onCreateView should use FragmentCallBinding.inflate
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentCallBinding.inflate(inflater)
return binding.root
}
onViewCreated should not assign the binding variable
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnSetupVideoCall.setOnClickListener{
(activity as MainActivity?)?.let {
val intent = Intent(it, One_to_One_VC::class.java)
it.startActivity(intent)
}
}
}
In the following code:
class LobbyFragment : Fragment() {
#Inject
lateinit var lobbyFragmentHelloService: LobbyFragmentHelloService
#BindView(R.id.lobby_fragment_hello)
lateinit var lobbyFragmentHelloTextView: TextView
lateinit var unbinder: Unbinder
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.lobby_fragment, container, false)
unbinder = ButterKnife.bind(this, view)
return view
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sayFragmentHello()
}
override fun onAttach(context: Context?) {
AndroidInjection.inject(this)
super.onAttach(context)
}
override fun onDestroyView() {
super.onDestroyView()
unbinder.unbind()
}
private fun sayFragmentHello() {
lobbyFragmentHelloTextView.text = lobbyFragmentHelloService.sayHello()
}
}
lobbyFragmentHelloTextView is never initialized. Butterknife is used to initialize this variable. Why is not initialized by the time sayFramentHello is called?
I'm not really sure what went wrong but to fix the issue, you can consider using kotlin built in synthetic binding and just get rid of butterknife. It's more efficient.
explained here