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.