Android BottomSheetDialogFragment blinking - android

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

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")
}

Android Navigation Component saveState and restoreState

Guys I need your help.
I use android navigation component and want to save backstack after user press button and restore it after. I found 2 methods
navController.saveState(): Bundle and navController.restoreState(bundle: Bundle).
But i have problem in use it. Seems like saveState work greate (i see bundle, and backstack inside), but i dont understand how to use restoreState, because the documentation says:
Restores all navigation controller state from a bundle. This should be called before any call to setGraph.
https://developer.android.com/reference/kotlin/androidx/navigation/NavController#restorestate
Okay, i did it, seems like backstack restored, but on screen i see first fragment (instead of the one I had when I saved it). What i do wrong?
Code:
FirstFragment
private val TAG = this::class.java.name
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
btn_forward.setOnClickListener { findNavController().navigate(R.id.action_firstFragment_to_secondFragment) }
btn_back.setOnClickListener { requireActivity().onBackPressed() }
}
}
SecondFragment
class SecondFragment : Fragment() {
private val TAG = this::class.java.name
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
btn_forward.setOnClickListener { findNavController().navigate(R.id.action_secondFragment_to_thirdFragment) }
btn_back.setOnClickListener { requireActivity().onBackPressed() }
}
}
ThirdFragment
class ThirdFragment : Fragment() {
private val TAG = this::class.java.name
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_third, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
btn_finish.setOnClickListener {
(requireActivity() as MainActivity).saveState() //here save bundle
requireActivity().finishAfterTransition()
}
btn_back.setOnClickListener { requireActivity().onBackPressed() }
}
}
MainActivity
class MainActivity : AppCompatActivity() {
private val TAG = "MySuperActivity"
lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "onCreate($savedInstanceState) called")
initNavController()
}
private fun initNavController() {
val navHostFragment = nav_host_fragment as NavHostFragment
val graphInflater = navHostFragment.navController.navInflater
val graph = graphInflater.inflate(R.navigation.main_graph)
navController = navHostFragment.navController
navHostFragment.childFragmentManager
if (App.instance.savedBundle != null) {
Log.d(TAG, "bundle: ${App.instance.savedBundle}")
navController.restoreState(App.instance.savedBundle)
graph.startDestination = R.id.thirdFragment
}
navController.graph = graph
Log.d(TAG, "navController.currentDestination: ${navController.currentDestination}")
Log.d(TAG, "navController.graph.startDestination: ${navController.graph.startDestination}")
}
fun saveState(){
App.instance.savedBundle = navController.saveState()
Log.d(TAG, "saveState() : ${App.instance.savedBundle}")
}
}
here some logs: logs
full code:github
I am not sure if my answer helps you, but I had many issues trying to save the navigation state from handling rotations. The issue that I had comes from an old version of the navigation component, I update to the most recent, and it fixes the issue:
def android_navigation = '2.3.4'
implementation "android.arch.navigation:navigation-fragment-ktx:$android_navigation"
implementation "android.arch.navigation:navigation-ui-ktx:$android_navigation"
implementation "androidx.navigation:navigation-dynamic-features-fragment:$android_navigation"

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

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 :)

How to change image in activity from fragment in Kotlin

In an android app I have an activity with several fragments. In one of these fragments I have an ImageButton. On click I want to let something happen in the activity directly, not in the fragment. In this case I want to set an image. Summed up, the ImageButton is in the fragment, but the ImageView I want to change on click is in the activity.
How do I achieve that? Whatever I've tried resulted in an app crash.
This is how my fragment.kt looks:
class Fragment1 : Fragment() {
companion object{
fun newInstance() = Fragment1()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_1, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
imageButton.setOnClickListener{
imageView.setImageResource(R.drawable.example)
}
}
}
class Fragment1 : Fragment() {
var callbacks: OnFragmentCallbacks? = null
override fun onAttach(context: Context?) {
super.onAttach(context)
callbacks = activity as OnFragmentCallbacks
}
interface OnFragmentCallbacks{
fun changeImage(resourceId: Int)
}
companion object{
fun newInstance() = Fragment1()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_1, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
imageButton.setOnClickListener{
callbacks?.changeImage(R.drawable.example)
}
}
In your Activity:
// Change FragmentName with name of your Fragment class
class MainActivity : AppCompatActivity(), FragmentName.OnFragmentCallbacks{
override fun changeImage(resouseId: Int){
imageView.setImageDrawable(getResources().getDrawable(resourceId))
// or
imageView.setImageResource(resourceId)
}
Just coded it in stackoverflow, may not be perfect

Kotlin Fragment

I have a simply Activity. In this activity I want start a fragment. But the Fragment doesn't start.
This is my Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//start Homefragment
startHomeFragment()
}
/**
* Create Homefragment
*/
private fun startHomeFragment() {
val homeFragment = fragmentManager.findFragmentByTag(statics.TAG) ?: HomeFragment()
fragmentManager.beginTransaction()
.replace(R.id.container, homeFragment, statics.TAG)
.commit()
}
And this is my Fragment
class HomeFragment : Fragment() {
object statics {
#JvmField val TAG = "Homefragment"
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return super.onCreateView(inflater, container, savedInstanceState)
inflater?.inflate(R.layout.fragment_home, container)
background_home.setBackgroundResource(R.drawable.gc_bg_home)
All the code after
return super.onCreateView(inflater, container, savedInstanceState)
is unreachable. Just read IDE warnings.
Also, layout becomes attached only if you returned it from onCreateView, i. e. return inflater.inflate(...).
In Kotlin the onCreateView should be on this way
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater!!.inflate(R.layout.input_field_frag, container, false)
}
If you want to add somthing inside you fragment you can use onViewCreated method and do whatever you want here
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//Here u can call function of add listners to button...
})
}
Like this you gonna create a safe propriate code
Solved:
class HomeFragment : Fragment() {
object statics {
#JvmField val TAG = "Homefragment"
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
Toast.makeText(activity, "HomeFragment", Toast.LENGTH_SHORT).show()
return inflater?.inflate(R.layout.fragment_home, container, false)
}
}

Categories

Resources