Home > Mobile >  Show BottomSheetDialogFragment when Click BottomNavigationView
Show BottomSheetDialogFragment when Click BottomNavigationView

Time:08-22

I am new to Android Development. I like to show Bottom Sheet Dialog Fragment when I click one of the menu buttons at the Bottom Navigation View. When I click the favorite button on the languages, it shows empty for the bottom sheet dialog. Is there other way to do it? Thanks.

Main Activity

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        replacementFragment(HomeFragment())


        binding.bottomNavigationView.setOnItemSelectedListener {
            when (it.itemId) {
                R.id.home -> replacementFragment(HomeFragment())
                R.id.language -> replacementFragment(LanguageFragment())
                // I cannot show the list on the fragment
                R.id.favourite -> showFavouriteBottomFragment()
            }
            true
        }

//        val bottomSheetFragment = FavouriteFragment()
//         bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.getTag() )

    }

    private fun replacementFragment(fragment: Fragment) {

        val fragmentManager = supportFragmentManager
        val fragmentTransaction = fragmentManager.beginTransaction()
        fragmentTransaction.replace(R.id.fragmentContainerView, fragment)
        fragmentTransaction.commit()
    }

    // I cannot get the following part to work....
    private fun showFavouriteBottomFragment() {

            val bottomSheetFragment = FavouriteFragment()
            bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.getTag() )
    }

}

Favourite Fragment

@AndroidEntryPoint
class FavouriteFragment: BottomSheetDialogFragment(){

    private  var _binding: FavouriteBottomSheetBinding ?= null
    private val binding get() = _binding!!
    private val viewModel: FavouriteViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        _binding = FavouriteBottomSheetBinding.inflate(inflater, container, false)
        val view = binding.root
       return view
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

//        val binding = FavouriteBottomSheetBinding.bind(view)

        val favouriteAdapter = FavouriteAdapter()

        binding.apply {
            favouriteLanguageList.apply{
                adapter = favouriteAdapter
                layoutManager = LinearLayoutManager(requireContext())
                setHasFixedSize(true)

            }
        }

        viewModel.favouriteLanguage.observe(viewLifecycleOwner){

            favouriteAdapter.submitList(it)
        }
    }
}

Bottom Menu

<menu xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@ id/home"
        android:icon="@drawable/ic_baseline_home_24"
        android:title="Home"
        tools:ignore="HardcodedText" />


    <item
        android:id="@ id/favourite"
        android:icon="@drawable/ic_baseline_favorite_24"
        android:title="Favourite"
        tools:ignore="HardcodedText" />


    <item
        android:id="@ id/language"
        android:icon="@drawable/ic_baseline_language_24"
        android:title="Language"
        tools:ignore="HardcodedText" />

</menu>

AppModule

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    fun provideTestString() = "This is a string we will inject"

    @Provides
    @Singleton
    fun provideDatabase(
        app: Application,
        callback: LanguageDatabase.Callback
    ) = Room.databaseBuilder(app, LanguageDatabase::class.java, "language_database")
        .fallbackToDestructiveMigration()
        .addCallback(callback)
        .build()

    @Provides
    fun provideLanguageDao(db: LanguageDatabase) = db.languageDao()



    @ApplicationScope
    @Provides
    @Singleton
    fun provideApplicationScope() =  CoroutineScope(SupervisorJob())

}

@Retention(AnnotationRetention.RUNTIME)
@Qualifier
annotation class ApplicationScope

Favourite Adapter

class FavouriteAdapter : ListAdapter<Language, FavouriteAdapter.FavouriteViewAHolder>(DiffCallback()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FavouriteViewAHolder {
        val binding = ItemFavouriteBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return FavouriteViewAHolder(binding)
    }

    override fun onBindViewHolder(holder: FavouriteViewAHolder, position: Int) {
        val currentItem = getItem(position)
        holder.bind(currentItem)
    }

    inner class FavouriteViewAHolder(private val binding: ItemFavouriteBinding) : RecyclerView.ViewHolder(binding.root){
        fun bind(language: Language){
            binding.apply {
                rbIsClicked.isChecked = language.isChecked
                tvFavouriteLanguage.text = language.language
            }
        }
    }

    class DiffCallback : DiffUtil.ItemCallback<Language>() {

        override fun areItemsTheSame(oldItem: Language, newItem: Language) =
            oldItem.id == newItem.id

        override fun areContentsTheSame(oldItem: Language, newItem: Language) = oldItem == newItem

    }
}

Favourite View Model

@HiltViewModel
class FavouriteViewModel @Inject constructor(
    private val languageDao: LanguageDao,
) : ViewModel() {

    val favouriteLanguage = languageDao.getFavouriteLanguageByName().asLiveData()

}

Preferences Manager

private const val TAG = "PreferencesManager"
private val Context.dataStore by preferencesDataStore("user_preferences")
enum class SortOrder { BY_NAME}
data class FilterPreferences(val sortOrder: SortOrder, val hideSelectedLanguage: Boolean, val selectedLanguage: String)

@Singleton
class PreferencesManager @Inject constructor(@ApplicationContext context: Context){

    private val dataStore =  context.dataStore
    val preferencesFlow = dataStore.data
        .catch { exception ->
            if(exception is IOException){
                Log.e(TAG, "Error reading preferences", exception)
                emit(emptyPreferences())
            }else{
                throw exception
            }
        }
        .map{ preferences ->
            val sortOrder = SortOrder.valueOf(
                preferences[PreferencesKeys.SORT_ORDER] ?:SortOrder.BY_NAME.name
            )
            val hideSelectedLanguage = preferences[PreferencesKeys.HIDE_SELECTED_LANGUAGE] ?: false
            val selectedLanguage = preferences[PreferencesKeys.SELECTED_LANGUAGE]?: "English"
            FilterPreferences(sortOrder, hideSelectedLanguage, selectedLanguage)

        }

    suspend fun updateSortOrder(sortOrder: SortOrder){
        dataStore.edit { preferences ->
            preferences[PreferencesKeys.SORT_ORDER] = sortOrder.name
        }
    }

    suspend fun updateHideSelectedLanguage(hideSelectedLanguage: Boolean){
        dataStore.edit { preferences ->
            preferences[PreferencesKeys.HIDE_SELECTED_LANGUAGE] = hideSelectedLanguage
        }
    }

    suspend fun updateSelectedLanguage(selectedLanguage: String){
        dataStore.edit{ preferences ->
            preferences[PreferencesKeys.SELECTED_LANGUAGE] = selectedLanguage
        }
    }

    private object PreferencesKeys{
        val SORT_ORDER = stringPreferencesKey("sort_order")
        val HIDE_SELECTED_LANGUAGE = booleanPreferencesKey("hide_selected_language")
        val SELECTED_LANGUAGE = stringPreferencesKey("selected_language")
    }

}

I have a Language Fragment which looks similar to Favourite Fragment.

CodePudding user response:

I find a temporary solution...but I still have a bug as I have the press the favourite button twice to show a list in the BottomSheetDialogFragment.

Is there a way, I can solve the problem? The first time I press the favourite button it doesn't shows a BottomSheetDialog fragment.... I have to press it again to show the list.

KC

In the MainActivity, I declare the class favouriteFragment.

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // declare the favroute fragment.
        val favouriteFragment = FavouriteFragment()

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        replacementFragment(HomeFragment())


        binding.bottomNavigationView.setOnItemSelectedListener {
            when (it.itemId) {
                R.id.home -> replacementFragment(HomeFragment())
                R.id.language -> replacementFragment(LanguageFragment())
                R.id.favourite -> 
                //  Pass the instace in the function. 
              showFavouriteBottomFragment(favouriteFragment)
            }
            true
        }

In the function in Main Activity

private fun showFavouriteBottomFragment(favouriteFragment: FavouriteFragment) {

        favouriteFragment.show(supportFragmentManager, favouriteFragment.tag)

    }

CodePudding user response:

I remove "setHasFixedSize(true)" and it can load the first time when I press the favorite button.

  • Related