BottomSheetDialogFragment does the enter animation again on `onStart`. How to halt it? - android

Everytime when the BottomSheetDialogFragment passes through the onStart lifecycle point, the enter window animation occurs again, as can be seen in the gif below.
What can be done to stop it from happening? I thought that it would only happen once, when the bottom action sheet was opened.
The code is as simple as that:
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bottomSheet = CustomBottomSheetFragment()
bottomSheet.show(supportFragmentManager, null)
}
}
CustomBottomSheetFragment.kt
class CustomBottomSheetFragment : BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = FrameLayout(requireContext())
view.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
800
)
view.setBackgroundColor(Color.CYAN)
return view
}
}
Obs.: "Don't keep activities" option is not enabled :)

Related

When app is onPause my DialogFragment is shown multiple times

I have a custom dialog in my App and i actually open it from my fragment like this:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btnScarica = view.findViewById(R.id.btnScarica)
btnScarica.setOnClickListener {
ScaricoDialog(articoliViewModel.articoli.value?.size).show(parentFragmentManager, "DialogScarico")
}
}
While the ScaricoDialog.kt looks like this:
class ScaricoDialog(private val listSize: Int? = 0): DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
dialog!!.window?.setBackgroundDrawableResource(R.drawable.round_corner)
return inflater.inflate(R.layout.scarica_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
override fun onStart() {
super.onStart()
val width = (resources.displayMetrics.widthPixels * 0.85).toInt()
dialog!!.window?.setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT)
}
}
When i lock the device so the app goes onPause and i unblock it i find lot of that dialogs open even when i opened just one...
i solved it by setting this onPause in my DialogFragment:
override fun onPause() {
super.onPause()
dialog?.dismiss()
}
But is it normal? is my solution right to do so?
set Dialog show method in onActivityCreate inside fragment method like this and stop dismiss in on pause
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
val width = (resources.displayMetrics.widthPixels * 0.85).toInt()
dialog!!.window?.setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT)
ScaricoDialog(articoliViewModel.articoli.value?.size).show(parentFragmentManager, "DialogScarico")
}

How can I call a context in a fragment for DrawableCompat.setTint with kotlin?

I want to change the color of a button in fragment by control of another button in mainActivity.
The code for the fragment is :
lass build_8p : Fragment() {
var brush_chosen = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val brush_color = arguments?.getString("brush")
ib0.setOnClickListener {
if (brush_chosen==1)
{
//val con = this.context
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(this.context,R.color.rndcolor1))
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_build_8p, container, false)
}
The variable brush_chosen will be took from the mainActivity.
Here I want to know how to put a correct input for
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(this.context,R.color.rndcolor1))
}
Since that line does not work.
Please tell me how and Thank you very much.
You can just use requireContext():
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(requireContext(),R.color.rndcolor1))
To use fragment context :
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(requireContext(),R.color.rndcolor1))
To use Activity context :
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(requireActivity(),R.color.rndcolor1))
both should work in your case

Android BottomSheetDialogFragment blinking

I startActivity from BottomSheetDialogFragment.
But when I finish the Activity, the BottomSheetDialogFragment is blinking.
My case is like this one BottomSheetDialog background blinking
But there is no solution.
Here is my screen shot
The code is simple and basic.
MainActivity.class
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bottomSheetFragment = BottomSheetFragment()
button.setOnClickListener {
bottomSheetFragment.show(supportFragmentManager, "")
}
}
}
BottomSheetFragment.class
class BottomSheetFragment: BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_bottom_sheet, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
button.setOnClickListener {
startActivity(Intent(context!!, Test2Activity::class.java))
}
}
}
Your Bottom sheet is not Blinking. its the effect of activity when you get back to MainActivity.
in your MainActivity Please implement overridePendingTransition before onCreate()
overridePendingTransition(0,0) // due to this default effect will remove

Trouble with NavController inside OnBackPressedCallback

I am getting a does not have a NavController set error inside a OnBackPressedCallback. Here is the code
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
fragmentView = inflater.inflate(R.layout.patient_info_fragment, container, false)
if(Utils.connectedToInternet()){
fragmentView.pastScreeningsButton.visibility = View.GONE
}
requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Navigation.findNavController(fragmentView).navigate(R.id.action_patientInfoFragment_to_patientsList)
}
})
setHasOptionsMenu(true)
return fragmentView
}
I am only getting this error when I come back into the fragment where this is implemented.
I have android:name="androidx.navigation.fragment.NavHostFragment" in the home fragment.
To clarify, I am using Navigation controller to do all my Navigation around my app and it works just fine. I only get this error inside this OnBackPressedCallback and only when the user navigates back into the fragment where this is implemented.
Let me know if you need to see any more of my code.
You might run into an issue with leaks of old instances of your fragment. Also it's not a good practice to store the created view within another variable like fragmentView. All in all your onCreateView implementation is doing too many things unrelated to its purpose.
I'd suggest to split up the functionality into relevant life-cycle methods and use the fragment.view directly within your callback. To not run into an issue with unattached views, you then bind and unbind the callback with the life-cycle.
class PatientInfoFragment: Fragment() {
private val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Navigation.findNavController(view).navigate(R.id.action_patientInfoFragment_to_patientsList)
}
}
override fun onCreate(
savedInstanceState: Bundle?
) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.patient_info_fragment, container, false)
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?
) {
if(Utils.connectedToInternet()){
view.pastScreeningsButton.visibility = View.GONE
}
}
override fun onStart() {
super.onStart()
requireActivity().onBackPressedDispatcher.addCallback(callback)
}
override fun onStop() {
callback.remove()
super.onStop()
}
}
The callback life-cycle binding can be bound with the fragment as lifecycle owner calling the other addCallback(LifecycleOwner, OnBackPressedCallback).
Additionally you could have a look into Android KTX and Kotlin Android Extensions to simplify your implementation.
Move your code in the onViewCreated and pass the view that is provided by the overriden method:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Navigation.findNavController(view).navigate(R.id.action_patientInfoFragment_to_patientsList)
}
})
}
If that also doesn't work, replace the .navigate() with popBastack(R.id.framgment_where_you_want to go, false), in case your previous fragment stays on the backStack

Base Navigation Fragment for multiple Fragments

Is it possible to create a Navigation Fragment to contain my navigation back button click logic.
Multiple Fragment's that have a back button would then be able then inherit from the Navigation Fragment.
I'm new to Kotlin development. As you see below the SigninFragment inflates the view, I'm not sure how to get a reference to the view & back button in a parent Navigation Fragment
class SigninFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_signin, container, false)
// Navigation back button logic
var headerBackButton = view.findViewById<ImageButton>(R.id.headerBackButton)
headerBackButton.setOnClickListener {
val navController = NavHostFragment.findNavController(this#SignInFragment)
navController.navigateUp()
}
return view
}
}
I'm not sure if I got your problem right but could this be the trick?
open class NavigationFragment() : Fragment() {
fun asignNavigationBackClickListener(backButton: View) {
backButton.setOnClickListener {
val navController = NavHostFragment.findNavController(this#NavigationFragment)
navController.navigateUp()
}
}
}
class SigninFragment : NavigationFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_signin, container, false)
asignNavigationBackClickListener(view.findViewById(R.id.headerBackButton))
return view
}
}
I think you can use this code for going back to the previous activity:
headerBackButton.setOnClickListener {
finish()
}

Categories

Resources