Android kotlin preferences spinner with values from arrays.xml - kotlin

settings_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
root_preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:dialogTitle="Select bluetooth adapter"
android:key="bluetoothName"
android:summary="Click to show a list to choose from"
android:title="Bluetooth adapter" />
<ListPreference
android:dialogTitle="Select units"
android:entries="#array/units_names"
android:entryValues="#array/units_values"
android:key="units"
android:summary="Click to show a list to choose from"
android:title="Units" />
</PreferenceScreen>
SettingsActivity.kt
class SettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_activity)
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
}
}
}
arrays.xml
<resources>
<string-array name="units_values">
<item>miles</item>
<item>km</item>
</string-array>
<string-array name="units_names">
<item>miles and mpg</item>
<item>km and l/100km</item>
</string-array>
</resources>
MainActivity.kt
...
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.toolbar, menu);
return true;
}
override fun onOptionsItemSelected( item: MenuItem) : Boolean {
when (item.itemId) {
R.id.toolbar_item_settings -> {
val intent: Intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
return true
}
}
return true
}
...
Why are the array values not showing in the spinner?

It's because the list item text colour has defaulted to black.
It needs:
<item name="textColorAlertDialogListItem">#color/text</item>

Related

No Adapter Attached RecyclerView

I want to implement my app. My app went smoothly, but I also got an error with 2022-05-31 14:14:32.663 8626-8626/id.kotlin.belajar E/RecyclerView: No adapter attached; skipping layout; skipping layout.
E/RecyclerView: No adapter attached; skipping layout; skipping layout
Home Activity:
class HomeActivity : DaggerAppCompatActivity(), HomeView {
#Inject
lateinit var presenter: HomePresenter
private lateinit var progressBar: ProgressBar
private lateinit var recyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
progressBar = findViewById(R.id.pb_home)
recyclerView = findViewById(R.id.rv_home)
presenter.discoverMovie()
}
override fun onShowLoading() {
progressBar.visibility = View.VISIBLE
}
override fun onHideLoading() {
progressBar.visibility = View.GONE
recyclerView.visibility = View.VISIBLE
}
override fun onResponse(results: List<Result<String>>) {
recyclerView.addItemDecoration(DividerItemDecoration(this#HomeActivity,
DividerItemDecoration.VERTICAL))
recyclerView.adapter = HomeAdapter(results)
}
override fun onFailure(t:Throwable) {
Log.e(HomeActivity::class.java.simpleName, "${t.printStackTrace()}")
}
}
Home Adapter:
class HomeAdapter (private val results: List<Result>):
RecyclerView.Adapter<HomeAdapter.HomeViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeViewHolder {
return HomeViewHolder(
LayoutInflater
.from(parent.context).inflate(
R.layout.item_home,
parent,
false
)
)
}
override fun onBindViewHolder(holder: HomeViewHolder, position: Int){
holder.bind()
}
override fun getItemCount(): Int{
return results.count()
}
inner class HomeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
fun bind() {
with(itemView) {
val title = findViewById<TextView>(R.id.original_title)
title.text
val overview = findViewById<TextView>(R.id.overview)
overview.text
}
}
}
}
Home Presenter:
class HomePresenter(private val view: HomeView, datasource: HomeDatasource) {
fun discoverMovie(){
view.onShowLoading()
val dataSource = Networkmodule.providesHttpAdapter(client =
OkHttpClient()).create(HomeDatasource::class.java)
dataSource.discoverMovie().enqueue(object : Callback<HomeResponse> {
override fun onResponse(call: Call<HomeResponse>, response: Response<HomeResponse>){
view.onHideLoading()
view.onResponse(((response.body()?.results ?: emptyList()) as List<Result<String>>))
}
override fun onFailure(call: Call<HomeResponse>, t:Throwable){
view.onHideLoading()
view.onFailure(t)
}
})
}
}
I need your help.
This is my .xml files:
activity_home:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".presentation.HomeActivity">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:elevation="4dp"
app:layout_constraintTop_toTopOf="parent"
app:title="Belajar"
app:titleTextColor="#color/black"/>
<ProgressBar
android:id="#+id/pb_home"
style="#style/Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateTint="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?android:attr/actionBarSize"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="#layout/item_home" />
</androidx.constraintlayout.widget.ConstraintLayout>
I can see two major problems here :
Adapter instantiation
You do not need to re-instantiate the adapter each time you receive data.
Just instanciate it in the onCreate method with an empty list and update the list each time you have new data (don't forget to call notify method).
And attach the adapter to the recyclerView in the onCreate method as well
Exemple
In your activity you need to :
Declare and instantiate your Adapter as a class attribute.
In the onCreate method attach it to the recyclerView
On the onResponse method call a new method of your adapter called " update "
class HomeActivity : DaggerAppCompatActivity(), HomeView {
#Inject
lateinit var presenter: HomePresenter
private lateinit var progressBar: ProgressBar
private lateinit var recyclerView: RecyclerView
private val homeAdapter = HomeAdapter(emptyList())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
progressBar = findViewById(R.id.pb_home)
recyclerView = findViewById(R.id.rv_home)
recyclerView.adapter = homeAdapter
presenter.discoverMovie()
}
override fun onShowLoading() {
progressBar.visibility = View.VISIBLE
}
override fun onHideLoading() {
progressBar.visibility = View.GONE
recyclerView.visibility = View.VISIBLE
}
override fun onResponse(results: List<Result<String>>) {
recyclerView.addItemDecoration(DividerItemDecoration(this#HomeActivity,
DividerItemDecoration.VERTICAL))
homeAdapter.update(results)
}
override fun onFailure(t:Throwable) {
Log.e(HomeActivity::class.java.simpleName, "${t.printStackTrace()}")
}
}
In your adapter :
Make results a mutableList
Create the update method
Clear the results list
Add your newResults list to your list
notifyDataSetChanged to redraw the list with new values
class HomeAdapter (private val results: MutableList<Result>):
RecyclerView.Adapter<HomeAdapter.HomeViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeViewHolder {
return HomeViewHolder(
LayoutInflater
.from(parent.context).inflate(
R.layout.item_home,
parent,
false
)
)
}
override fun onBindViewHolder(holder: HomeViewHolder, position: Int){
holder.bind()
}
override fun getItemCount(): Int{
return results.count()
}
fun update(newResults: List<Result>) {
results.apply {
clear()
addAll(newResults)
}
notifyDataSetChanged()
}
inner class HomeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
fun bind() {
with(itemView) {
val title = findViewById<TextView>(R.id.original_title)
title.text
val overview = findViewById<TextView>(R.id.overview)
overview.text
}
}
}
}
Layout manager missing ?
We don't have your xml code so I don't know if you added the layoutManager on the xml like this (assuming you want a linearManager) :
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
You can do it programaticaly using the layoutManager attribute on the recyclerView :
recyclerView.layoutManager = LinearLayoutManager()
You can set it in the onCreate method (if it is an activity) or onViewCreated (if it's a fragment) before attaching your adapter to the recyclerView
To avoid errors like that, the best way is to setup your recyclerView as soon as possible in the activity (onCreate) or fragment (onViewCreated) lifecycle.

How to implement nested paging in android kotlin?

I have a recyclerview , for i using pagin 3 with coroutine live data .
but child recyclerview also have paginate data so how can i perform this nested pagination in android kotlin.
So , I done this with pagination for child recyclerview inside recyclerview .
Firstly of all call api for fetch dates and perform api for every date at same time when date are fetching.
so structure like this...
lateinit var adapter: WeeklyAdapter
lateinit var dayAdapter: DayDetailsPagingAdapter
private fun observeData() {
viewModel.weeklyAcquiringDetails(AcquiringVM.WEEKLY, "").observe(this){
wsWithLoader(it){
binding.rvAcquiringWeeklyDetails.adapter = WeeklyAdapter(it.data!!.data, object : WeeklyAdapter.OnPerformApi{
override fun performApi(date: String, rvMonthly: RecyclerView) {
dayAdapter = DayDetailsPagingAdapter(object : DayDetailsPagingAdapter.OnClick{
override fun onClick(result: DayAcquiring.Data) {}
})
rvMonthly.adapter = dayAdapter
lifecycleScope.launchWhenCreated {
viewModel.getDayAcquiringDetails(date).collectLatest { data ->
dayAdapter.submitData(data)
}
}
}
})
}
}
}
Weekly Adapter
class WeeklyAdapter (
val list: List<WeeklyAcquiring.Data>,
val action: OnPerformApi
) : RecyclerView.Adapter<WeeklyAdapter.ViewHolder>() {
#NonNull
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.list_monthly, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val result = list[position]
holder.binding.apply {
tvDate.text = changeDateFormat(result.doctorScheduleDate,"yyyy-MM-dd","E, dd MMM yyyy")
action.performApi( result.doctorScheduleDate , rvMonthly)
}
}
override fun getItemCount(): Int {
return list.size
}
inner class ViewHolder(binding: ListMonthlyBinding) : BaseViewHolder<ListMonthlyBinding>(binding) {}
interface OnPerformApi{
fun performApi(date : String, rvMonthly: RecyclerView)
}
}
list_monthly_layout
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvDate"
style="#style/TVBold"
android:layout_marginTop="#dimen/_5sdp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/_12sdp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="May 2022" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvMonthly"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_10sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintStart_toStartOf="parent"
tools:listitem="#layout/list_acquiring_details"
app:layout_constraintTop_toBottomOf="#+id/tvDate" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
DayDetailsPagingAdapter
class DayDetailsPagingAdapter (private val onClick: OnClick) : PagingDataAdapter<DayAcquiring.Data, DayDetailsPagingAdapter.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(ListAcquiringDetailsBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
#SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val result = getItem(position)!!
holder.binding.apply {
data = result
tvName.text = result.userName
tvAmount.text = "€ ${result.amount}"
}
}
class ViewHolder(val binding: ListAcquiringDetailsBinding) : RecyclerView.ViewHolder(binding.root) {}
private class DiffCallback : DiffUtil.ItemCallback<DayAcquiring.Data>() {
override fun areItemsTheSame(
oldItem: DayAcquiring.Data,
newItem: DayAcquiring.Data
): Boolean = oldItem == newItem
override fun areContentsTheSame(
oldItem: DayAcquiring.Data,
newItem: DayAcquiring.Data
): Boolean = oldItem == newItem
}
interface OnClick {
fun onClick(result: DayAcquiring.Data )
}
}
**in viewmodel **
fun getDayAcquiringDetails( date: String ) = apiHelper.getDayAcquiringDetails( date ).cachedIn(viewModelScope)
fun weeklyAcquiringDetails( filter: String , date: String) = apiHelper.weeklyAcquiringDetails( filter , date)
hope you like this .

Recycler View not displaying inside a Fragment

I'm using Recycler view to show items in my Fragment named Recent History. I want to display user data from firebase to my recent history Fragment. But the recycler view is not showing on the fragment. Please Help me out in this. What did I do wrong here? or what's the solution so that my fragment shows the recycler view.
Recent History Fragment Code:
`
class recent_history : Fragment(R.layout.fragment_recent_history) {
private var binding: FragmentRecentHistoryBinding? = null
private lateinit var auth: FirebaseAuth
var database: FirebaseDatabase? = null
var databaseReference: DatabaseReference? = null
private lateinit var userArrayList: ArrayList<User>
private lateinit var myAdapter: AdapterClass
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentRecentHistoryBinding.inflate(inflater, container, false)
return binding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
auth = FirebaseAuth.getInstance()
database = FirebaseDatabase.getInstance()
databaseReference = database?.reference!!.child("Users").child("result")
userArrayList= arrayListOf()
myAdapter=AdapterClass(userArrayList)
binding?.recyclerview.apply {
binding?.recyclerview?.adapter = myAdapter
var linearLayoutManager = LinearLayoutManager(activity)
binding?.recyclerview?.layoutManager = linearLayoutManager
binding?.recyclerview?.setHasFixedSize(true)
}
getData()
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
private fun getData() {
val user = auth.currentUser
databaseReference?.child(user?.uid!!)
databaseReference!!.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
if (snapshot.exists()) {
for (data in snapshot.children) {
var model = data.getValue(User::class.java)
userArrayList.add(model!!)
}
}
}
override fun onCancelled(error: DatabaseError) {
Log.e("cancel", error.toString())
}
})
}
}
`
Fragment Recent History Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
tools:context=".recent_history">
<TextView
android:id="#+id/profiletitle"
android:layout_width="389dp"
android:layout_height="46dp"
android:layout_marginStart="4dp"
android:layout_marginTop="28dp"
android:fontFamily="monospace"
android:text="Recent Search History"
android:textAlignment="center"
android:textColor="#color/Twit"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</TextView>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="220dp"
android:layout_height="664dp"
android:layout_marginBottom="100dp"
android:orientation="vertical"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/profiletitle"
tools:listitem="#layout/adapterview">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
I'm sending data to firebase from another Fragment named keyword Fragment.
Code of keyword fragment:
class keywordfrag : Fragment() {
private var binding: FragmentKeywordfragBinding? = null
private lateinit var auth: FirebaseAuth
var database: FirebaseDatabase? = null
var databaseReference: DatabaseReference? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentKeywordfragBinding.inflate(inflater, container, false)
return binding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
auth = FirebaseAuth.getInstance()
database = FirebaseDatabase.getInstance()
val user = auth.currentUser
databaseReference?.child(user?.uid!!)
databaseReference = database?.getReference("Users")?.child("result")
binding?.analyzebtn?.setOnClickListener {
sendData()
}
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
private fun sendData() {
val keywordtext = binding?.userenteredkeyword?.text.toString().trim()
val timestamp = Timestamp(System.currentTimeMillis())
val timendate = timestamp.toString().trim()
// val username=auth.currentUser?.uid.toString().trim()
// val email=auth.currentUser?.email.toString().trim()
if (TextUtils.isEmpty(keywordtext)) {
binding?.userenteredkeyword?.error = "keyword can not be Empty"
} else {
val model = User(keywordtext, timendate)
val user = auth.currentUser
databaseReference?.child(user?.uid!!)?.setValue(model)
binding?.userenteredkeyword?.setText("")
val currentUser = auth.currentUser
val currentUserdb = databaseReference?.child((currentUser?.uid!!))
currentUserdb?.child("keywordtext")?.setValue(keywordtext)
currentUserdb?.child("timendate")?.setValue(timendate)
}
}
}
Adapter Class:
package com.example.emotela_finalyearproject
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.emotela_finalyearproject.databinding.AdapterviewBinding
import kotlin.collections.ArrayList
class AdapterClass(var list:ArrayList<User>) :RecyclerView.Adapter<AdapterClass.ViewHolder>() {
class ViewHolder(val binding: AdapterviewBinding) : RecyclerView.ViewHolder(binding.root) {
var keyword = binding.keywordtv
var timenddate=binding.timendatetv
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = AdapterviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
with(holder) {
with(list[position]) {
keyword.text = this.keywordtext
timenddate.text= this.timendate
}
}
}
}
Adapter view Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardElevation="8dp"
app:cardCornerRadius="8dp"
android:layout_margin="16dp">
<LinearLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginVertical="6dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="336dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="#+id/keywordtitle"
android:layout_width="141dp"
android:layout_height="35dp"
android:fontFamily="monospace"
android:text="searched word: "
android:textSize="10sp"
android:textStyle="bold">
</TextView>
<TextView
android:id="#+id/keywordtv"
android:layout_width="143dp"
android:layout_height="36dp"
android:fontFamily="monospace"
android:textSize="10sp">
</TextView>
<TextView
android:id="#+id/timeanddatetitle"
android:layout_width="160dp"
android:layout_height="36dp"
android:fontFamily="monospace"
android:text="Time and Date: "
android:textSize="10sp"
android:textStyle="bold">
</TextView>
<TextView
android:id="#+id/timendatetv"
android:layout_width="171dp"
android:layout_height="48dp"
android:fontFamily="monospace"
android:textSize="10sp">
</TextView>
<LinearLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginVertical="6dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="336dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
Result in Emulator:
You need to calll
imageAdapter.notifyDataSetChanged()
after you fetch the data from firebase.

Show and hide a View with a slide up/down animation android studio

I have a problem hiding the BottomNavigationView since there is a space left over and I don't know what to do in that case, I don't know what property to use so that the entire BottomNavigationView is hidden, I would appreciate any advice or solution to my problem
Activity_main.XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/body_container"
app:hideOnScroll="true"
android:background="#color/light_color"
tools:context=".navigation_bottom">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="30dp"
android:elevation="2dp"
android:background="#drawable/round_corner"
app:menu="#menu/item_menu"
app:itemRippleColor="#android:color/transparent"
app:itemIconSize="30dp"
app:labelVisibilityMode="labeled"
app:itemTextColor="#drawable/text_selector"
app:itemIconTint="#drawable/item_selector"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:hideOnScroll="true"
android:layout_gravity="bottom"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Activity_navigation_bottom
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/body_container"
app:hideOnScroll="true"
android:background="#color/light_color"
tools:context=".navigation_bottom">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="30dp"
android:elevation="2dp"
android:background="#drawable/round_corner"
app:menu="#menu/item_menu"
app:itemRippleColor="#android:color/transparent"
app:itemIconSize="30dp"
app:labelVisibilityMode="labeled"
app:itemTextColor="#drawable/text_selector"
app:itemIconTint="#drawable/item_selector"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:hideOnScroll="true"
android:layout_gravity="bottom"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
ScrollHandler.kt
class ScrollHandler : CoordinatorLayout.Behavior<BottomNavigationView>() {
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: BottomNavigationView,
dependency: View
): Boolean {
return dependency is FrameLayout
}
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout,
child: BottomNavigationView,
directTargetChild: View,
target: View,
nestedScrollAxes: Int
): Boolean {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
}
override fun onNestedPreScroll(
coordinatorLayout: CoordinatorLayout,
child: BottomNavigationView,
target: View,
dx: Int,
dy: Int,
consumed: IntArray
) {
if (dy < 0) {
showBottomNavigationView(child)
} else if (dy > 0) {
hideBottomNavigationView(child)
}
}
private fun hideBottomNavigationView(view: BottomNavigationView) {
view.animate().translationY(view.height.toFloat())
}
private fun showBottomNavigationView(view: BottomNavigationView) {
view.animate().translationY(0f)
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var bottomNavigationView: BottomNavigationView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
bottomNavigationView = binding.space as BottomNavigationView
val layoutParams = bottomNavigationView!!.layoutParams as CoordinatorLayout.LayoutParams
layoutParams.behavior = ScrollHandler()
setContentView(binding.root)
initRecyclerView()
}
I don't know what to try

RecyclerView view doesn't change using background_selector

I'm Trying to toggle item background color upon item selection.
I can see it's logic is working yet the background wouldn't change.
The log prints show the selctions indeed work, yet the background not.
From background_selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/holo_green_light" android:state_pressed="false" android:state_selected="true" />
<item android:drawable="#android:color/holo_purple" android:state_selected="false" />
</selector>
from task_row.xml:
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="3dp"
app:cardElevation="3dp"
android:id="#+id/tasksCardView"
android:background="#drawable/background_selector"
app:cardUseCompatPadding="true">
From Adapter code:
class MyTasksAdapter (
val arrayList: ArrayList<Task>,
val selectedItemsList: ArrayList<Task>,
val deletedItemsList: ArrayList<String>) :
RecyclerView.Adapter<MyTasksAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private var cardView: CardView = itemView.tasksCardView
private val selectedItems = SparseBooleanArray()
override fun onClick(view: View) {
if (selectedItems[adapterPosition, false]) {
selectedItems.delete(adapterPosition)
cardView.isSelected = false
Log.d("Item selected AA", "position: $position")
}
else {
selectedItems.put(adapterPosition, true)
view.isSelected = true
Log.d("Item selected BB", "position: $position")
}
}
init {
itemView.setOnClickListener(this)
}
Tried also changing cardview to view, but it didn't help either.
class MyTasksAdapter (
val arrayList: ArrayList<Task>,
val selectedItemsList: ArrayList<Task>,
val deletedItemsList: ArrayList<String>) :
RecyclerView.Adapter<MyTasksAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
//private lateinit var item: ClipData.Item
private var cardView: CardView = itemView.tasksCardView
private val selectedItems = SparseBooleanArray()
override fun onClick(view: View) {
if (selectedItems[adapterPosition, false]) {
selectedItems.delete(adapterPosition)
view.isSelected = false
Log.d("Item selected AA", "position: $position")
}
else {
selectedItems.put(adapterPosition, true)
view.isSelected = true
Log.d("Item selected BB", "position: $position")
}
}
init {
itemView.setOnClickListener(this)
}
Appreciate your kind help.
Working now.
Moved it to the relative_layout header: instead of cardview_layout header
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="3dp"
app:cardElevation="3dp"
android:id="#+id/tasksCardView"
android:hapticFeedbackEnabled="true"
app:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
**android:background="#drawable/background_selector"**
android:padding="16dp">