When attempting to use Kotlin Extensions within a RecyclerView.Adapter to refer to Views in an XML layout file, Intellij cannot recognize the Views by their IDs, even with seemingly correct imports. The odd thing about this is that it will work inside of an Activity or Fragment. Is there additional context needed for this to work in a RecyclerView.Adapter?
Intellisense not picking up Views in a RecyclerView.Adapter implementation:
View was found with practically the same imports
And here is my XML, just in case
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
>
<LinearLayout
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="#+id/tv_list_repo_name"
android:text="#string/repo_name"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tv_item_repo_description"
android:text="#string/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="#+id/tv_item_forks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="#drawable/ic_fork"
android:text="10"
android:gravity="end"/>
<TextView
android:id="#+id/tv_item_stars"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="#drawable/ic_star"
android:gravity="end"
android:text="14,000"
/>
</LinearLayout>
</LinearLayout>
It seems you're trying to get the view outside the onBindViewHolder.
Please take a look at this sample:
import kotlinx.android.synthetic.main.row_badges_item.view.*
class BadgesAdapter(private val mActivity: Activity) : RecyclerView.Adapter<BadgesAdapter.ViewHolder>() {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(position)
}
override fun getItemCount(): Int {
ba // Error here
return mData.size
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(position: Int) {
with(itemView) {
val badge = mData[position]
badges_title.text = badge.badgeTitle // Fine here
}
}
}
}
Hope that helps. Thanks. :)
Related
I am trying to build a layout in which there is a recyclerview where each item has three edittexts horizontally aligned. I want to add the next item when a button is pressed.
This the design I am trying to build
This is the Adapter class for the recycler view
class AddProjectAdapter(private val itemsList : ArrayList<ItemDetails>) : RecyclerView.Adapter<AddProjectAdapter.AddProjectViewHolder>() {
inner class AddProjectViewHolder(private val binding : AddProjectItemViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item : ItemDetails){
binding.item = item
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddProjectViewHolder{
return AddProjectViewHolder(AddProjectItemViewBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(holder: AddProjectViewHolder, position: Int) {
holder.bind(itemsList[position])
}
override fun getItemCount(): Int = itemsList.size
}
Layout file for the item add_project_item_view.xml
`
<?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">
<data>
<variable
name="item"
type="com.example.hero.models.ItemDetails" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.card.MaterialCardView
android:id="#+id/item_name_cardview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:flow_horizontalBias="3"
app:cardBackgroundColor="#color/light_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="#id/g_v_1"
android:layout_marginRight="5dp">
<EditText
android:id="#+id/item_name_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Item Name"
android:text="#={item.itemName}"
android:textColor="#color/t_dark"
android:fontFamily="#font/metropolislight"
android:textSize="14dp"
android:textColorHint="#color/t_dark"
android:background="#null"
android:padding="10dp" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="#+id/rate_unit_cardview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:flow_horizontalBias="2"
android:layout_marginRight="5dp"
app:cardBackgroundColor="#color/light_background"
app:layout_constraintStart_toEndOf="#id/g_v_1"
app:layout_constraintEnd_toEndOf="#id/g_v_2">
<EditText
android:id="#+id/rate_unit_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Rate/Unit"
android:text="#={item.rate}"
android:textColorHint="#color/t_dark"
android:textColor="#color/t_dark"
android:fontFamily="#font/metropolislight"
android:textSize="14dp"
android:padding="10dp"
android:background="#null" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="#+id/unit_cardview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:flow_horizontalBias="2"
app:cardBackgroundColor="#color/light_background"
app:layout_constraintStart_toEndOf="#id/g_v_2"
app:layout_constraintEnd_toEndOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/unit_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:background="#null"
android:fontFamily="#font/metropolislight"
android:hint="Unit"
android:padding="10dp"
android:text="#={item.unit}"
android:textColor="#color/t_dark"
android:textColorHint="#color/t_dark"
android:textSize="14dp" />
<ImageView
android:id="#+id/drop_down_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="#drawable/dropdown"
android:layout_centerVertical="true" />
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/g_v_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.4" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/g_v_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
`
//code of the activity in which the recycler view is present
private val itemsList : ArrayList<ItemDetails> = ArrayList()
private lateinit var addProjectAdapter: AddProjectAdapter
private lateinit var binding: ActivityAddProjectBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAddProjectBinding.inflate(layoutInflater)
setContentView(binding.root)
setAdapter()
setListner()
}
private fun setAdapter(){
addProjectAdapter = AddProjectAdapter(itemsList)
binding.itemDetailsRecyclerview.apply {
layoutManager = LinearLayoutManager(this#AddProject)
adapter = addProjectAdapter
}
}
override fun onClick(v : View?) {
when(v?.id){
binding.addItemButton.id -> {
itemsList.add(ItemDetails())
addProjectAdapter.notifyItemInserted(itemsList.size-1)
}
}
}
private fun setListner(){
binding.addItemButton.setOnClickListener(this)
}
data class ItemDetails(
var itemName : String = "",
var rate : String = "",
var unit : String = "")
And my recyclerview id is item_details_recyclerview.
Output for the above code
When I click the add button the item added is not visible but the add button moves down.
Can someone help me out with this issue? And also if you could provide some better approach it would be great.
Thanks in advance.
Change height of ConstraintLayout from add_project_item_view.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
to this
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
This has been asked before but those solutions didn't help me out. I have a RecyclerView that is scrollable and only partially visible on the screen at any one time. It holds a list of RadioButtons and some text related to each item. When you click on a RadioButton, the last button selected prior to this one should turn off. It does not. Each button you click gets selected and the other ones that you selected before stay selected as well.
It's set up like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white"
tools:context=".ui.SettingsActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/video_settings"
android:textColor="#color/black"
android:textStyle="bold"
android:textSize="#dimen/clickableTextSize"
android:layout_alignParentStart="true"
/>
</RelativeLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="100"
android:gravity="bottom"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="15"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:text="#string/set_resolution_and_fps"
android:textSize="#dimen/history_text_size"
android:gravity="center_vertical"
android:background="#color/grey_200"
android:textColor="#color/black"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_video_resolution"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="80"
android:layout_marginTop="5dp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/submitVideoSettings"
android:text="#string/submit"
android:layout_marginBottom="5dp"
android:textColor="#color/black"
android:layout_gravity="center|bottom"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
The recycler looks like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/resolutionRVRadioButton"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/resolutionRVTV"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="#string/at_symbol"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/framesPerSecondRVTV"
android:layout_marginStart="5dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/fps"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
The code for the adapter looks like this.
class ResolutionRVAdapter(private val sharedNavAndMenuViewModel: SharedNavAndMenuViewModel,
private val lastResolutionSelected: String,
private val capabilityDataList: List<CameraCapabilitySpecificFPS>) : RecyclerView.Adapter<CameraResolutionRVAdapter.ViewHolder>(){
private var lastCheckedPosition = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CameraResolutionRVAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.camera_resolution_recycler_item, parent, false)
val viewHolder = ViewHolder(v)
Timber.i("Added viewHolder: ${viewHolder.resolutionText.text}")
return ViewHolder(v)
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val resolutionRadioButton : RadioButton = itemView.findViewById(R.id.resolutionRVRadioButton)
val resolutionText : TextView = itemView.findViewById(R.id.resolutionRVTV)
val framesPerSecondText : TextView = itemView.findViewById(R.id.framesPerSecondRVTV)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val child = capabilityDataList[position]
Timber.i("onBindViewHolder currently working with resolution ${child.resolution} range of $child.range")
holder.resolutionText.text = child.resolution.toString()
holder.framesPerSecondText.text = child.fps
Timber.d("OnBindViewholder and lastResolutionSelected = $lastResolutionSelected")
if(lastResolutionSelected.isEmpty()) {
if(position == 0) {
holder.resolutionRadioButton.isChecked = true
Timber.i("No last resolution was selected. Setting index 0 to true")
}
} else if(lastResolutionSelected == holder.resolutionText.text.toString()) {
Timber.i("An old resolution of ${holder.resolutionText.text} was selected. Setting index $position to true")
holder.resolutionRadioButton.isChecked = true
}
holder.resolutionRadioButton.setOnClickListener {
Timber.i("Index hit was: $position resolution at that index was: ${holder.resolutionText.text}")
if(holder.resolutionRadioButton.isChecked) {
//Button was already checked...must be the same button hit before...nothing to do
} else {
holder.resolutionRadioButton.isChecked = true
runOnUiThread {
notifyItemChanged(lastCheckedPosition)
notifyItemChanged(position)
}
lastCheckedPosition = position
}
}
}
override fun getItemCount(): Int {
return capabilityDataList.size
}
}
Can anyone tell me what it is I'm doing wrong?
I have a recyclerView inside a fragment, this fragment is located in a viewpager2.
I read data from server and convert them to my ModelClass, them create an ArrayList and pas this array list to recyclerView.
here is my recyclerView item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/main_icon_background"
android:elevation="5dp"
android:layoutDirection="rtl"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="#+id/image"
android:layout_width="120dp"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#color/black" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.6"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="#style/vazir_font"
android:textColor="#color/black" />
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:ellipsize="end"
android:maxLines="3"
android:textAppearance="#style/vazir_font"
android:textColor="#color/gray"
android:textSize="13sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:layout_marginStart="20dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="8dp"
android:alpha="0.5"
android:background="#color/gray" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/source"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_weight="0.8"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="#style/vazir_font"
android:textColor="#color/colorPrimaryDark"
android:textSize="13sp" />
<TextView
android:id="#+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="end"
android:textAppearance="#style/vazir_font"
android:textColor="#color/colorAccent"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
and here is my recyclerView adapter:
class NewsRecyclerViewAdapter : RecyclerView.Adapter<NewsRecyclerViewAdapter.ViewHolder>() {
private val items = ArrayList<NewsAdapterModel>()
lateinit var onClick: NewsTutorialClickListener
fun add(list: ArrayList<NewsAdapterModel>) {
items.clear()
items.addAll(list)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.news_recycler_model, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding(items[position])
}
override fun getItemId(position: Int): Long {
return items[position].id.hashCode().toLong()
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun binding(model: NewsAdapterModel) {
itemView.setOnClickListener {
onClick.onClick(model.id)
}
itemView.title.text = model.title
itemView.description.text = model.description
itemView.date.text = Arrange().persianConverter(model.date)
itemView.source.text = model.source
Glide.with(itemView.context)
.load(model.image)
.placeholder(R.mipmap.logo)
.into(itemView.image)
}
}
}
I used this recycler view in my fragment just like this:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
adapter.onClick = this
binding.recyclerView.layoutManager = LinearLayoutManager(context)
binding.recyclerView.adapter = adapter
binding.recyclerView.setHasFixedSize(true)
binding.recyclerView.setItemViewCacheSize(20)
scope.launch {
withContext(Dispatchers.Default) {
fetchNews()
}
}
}
my problem is : when I scroll recycler view for first time it is not smooth and it seems some frames are jumped, but when I reach end of recyclerView and scroll to up then scroll down it is very smooth and find. how can I solve this issue?
I also should mention that Items of recyclerView are not much, it's around 10 items.
remove
recyclerView.setHasFixedSize(true)
actually it can cause no harm and indeed improves performance, because recyclerView won't bother calculating size of viewHolders evrytime inside onBindViewHolder. But you have all your TextViews with wrap_content height which will most certainly cause some broken UI in future.
remove
recyclerView.setItemViewCacheSize(20)
This function forces RecyclerView to prematurely inflate and bind 20 extra ViewHolders, so that it can use them straight away without calling OncreateViewHolder and OnBindViewHolder. You should'nt play around with this and just go with the defaults. Although 20 extra viewholders shouldn't have been a big deal, i guess maybe RecyclerView got confused because you forced it create extra 20 on top of existing 10, while you list only contains 10 items. It was taking time to create those extra viewHolders blocking ui thread, but after they were created it seemed smooth.
You don't need to add these lines
binding.recyclerView.setHasFixedSize(true)
binding.recyclerView.setItemViewCacheSize(20)
Please remove these lines
I'm in the process of fiddling my way to a working app using Kotlin and I have hit a roadblock when trying to implement OnClickListeners for my three buttons. I have my RecyclerView populate properly, but despite following the recommendations on this SO post (except in Kotlin) and following the documentation, though I am still having trouble getting the implementation to work.
The code below is my adapter class for the implementation.
class BrowseHabitsAdapter(private val habits: ArrayList<Habit>) :
RecyclerView.Adapter<BrowseHabitsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.habit_card, parent, false)
return ViewHolder(itemView, object: HabitClickListener {
override fun onDecrease(position: Int) {
val streak = itemView.dayCounter.text.toString().toInt()
itemView.dayCounter.text = streak.dec().toString()
}
override fun onIncrease(position: Int) {
val streak = itemView.dayCounter.text.toString().toInt()
itemView.dayCounter.text = streak.inc().toString()
}
override fun onEdit(position: Int) {
TODO("Change Activity to Edit")
}
})
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = habits[position]
holder.habitTitle.text = currentItem.title
holder.streak.text = currentItem.streak.toString()
}
override fun getItemCount() = habits.size
class ViewHolder(itemView : View, listener : HabitClickListener) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
val habitTitle: TextView = itemView.habitTitle
val streak: TextView = itemView.dayCounter
val decreaseCounterButton : Button = itemView.decreaseCounterButton
val increaseCounterButton : Button = itemView.increaseCounterButton
val listener = listener
init {
decreaseCounterButton.setOnClickListener(this)
increaseCounterButton.setOnClickListener(this)
}
override fun onClick(v: View?) {
when (itemView.id) {
itemView.decreaseCounterButton.id -> listener.onDecrease(this.layoutPosition)
itemView.increaseCounterButton.id -> listener.onIncrease(this.layoutPosition)
}
}
}
interface HabitClickListener {
fun onDecrease(position : Int)
fun onIncrease(position : Int)
fun onEdit(position : Int)
}
}
and the following is my XML code defining one of my cards:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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:id="#+id/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
app:cardBackgroundColor="#eeeeee"
app:cardCornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/cardHeader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="#+id/habitTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:text="#string/default_card_title"
android:textSize="18sp" />
<Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1" />
<ImageView
android:id="#+id/settingsIcon"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="bottom"
android:layout_marginRight="10dp"
app:srcCompat="#android:drawable/ic_menu_manage" />
</LinearLayout>
<LinearLayout
android:id="#+id/cardControls"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="#+id/decreaseCounterButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="-"
android:textAllCaps="false"
android:textSize="30sp" />
<Space
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="#+id/dayCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:fontFamily="sans-serif-medium"
android:text="0"
android:textAlignment="center"
android:textSize="30sp"
android:textStyle="bold" />
<Space
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<Button
android:id="#+id/increaseCounterButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="+"
android:textSize="30sp" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
Any additional explanation that can be provided as to what I did wrong and what is going on in detail would be really appreciated!
You are in kotlin so need to implement View.OnClickListener you can directly use setOnClickListener on any view.
Inside your ViewHolder Class:
itemView.increaseCounterButton.setOnClickListener{
listener.onIncrease(this.layoutPosition)
}
itemView.decreaseCounterButton.setOnClickListener{
listener.onDecrease(this.layoutPosition)
}
It should be view?.id instead of itemView.id
override fun onClick(v: View?) {
when (v?.id) {
itemView.decreaseCounterButton.id -> listener.onDecrease(this.layoutPosition)
itemView.increaseCounterButton.id -> listener.onIncrease(this.layoutPosition)
}
}
Additionally, your code with bugs. You handle HabitClickListener only update UI, when you scroll your data will be update base on habits. It means it will be revert when you scroll. Make sure streak of model Habit is var
return ViewHolder(itemView, object: HabitClickListener {
override fun onDecrease(position: Int) {
habits[position].streak = habits[position].streak.dec()
itemView.dayCounter.text = shabits[position].streak.toString()
}
override fun onIncrease(position: Int) {
habits[position].streak = habits[position].streak.inc()
itemView.dayCounter.text = shabits[position].streak.toString()
}
override fun onEdit(position: Int) {
TODO("Change Activity to Edit")
}
})
Using a spinner on a fragment, all seems to be good, but when I add an EditText and set focus in EditText, my spinner listener won't respond...
I have tried a lot of things, like change my spinner data, delete all the disruptive code, change layouts.
<FrameLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:background="#drawable/button_orange"
android:layout_marginBottom="10dp" android:layout_marginTop="10dp">
<androidx.appcompat.widget.AppCompatSpinner
android:layout_width="wrap_content"
android:layout_height="match_parent" android:id="#+id/spinnerCountries"
android:spinnerMode="dropdown" android:layout_margin="5dp"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#color/white"/>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/input_layout_phone"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#color/orange">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/input_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="phone"
android:hint="#string/hint_phone_number"
android:importantForAutofill="noExcludeDescendants"
android:maxLength="20"
android:drawableRight="#mipmap/icon_help_phone"
android:textColor="#color/orange"
tools:ignore="UnusedAttribute" android:background="#null" android:fitsSystemWindows="true"/>
</com.google.android.material.textfield.TextInputLayout>
</FrameLayout>
mSpinnerCountries!!.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(arg0: AdapterView<*>, arg1: View, position: Int, arg3: Long) {
prefs!!["country_position"] = position
val mSelectedCountry = arg0.selectedItem as Pays?
prefs!!["user_countrycode"] = mSelectedCountry?.code
prefs!!["carrier_countryiso"] = mSelectedCountry?.iso
prefs!!["country_prefix"] = mSelectedCountry?.prefix
Timber.d("Item selected on spinner : code ${mSelectedCountry?.code}, iso ${mSelectedCountry?.iso}, prefix ${mSelectedCountry?.prefix}")
mEditText!!.text!!.clear()
mEditText!!.text!!.clearSpans()
mEditText!!.setText(mSelectedCountry?.prefix)
mEditText!!.setSelection(mSelectedCountry?.prefix!!.length)
}
override fun onNothingSelected(arg0: AdapterView<*>) {
val mSelectedCountry = arg0.selectedItem as Pays?
prefs!!["user_countrycode"] = mSelectedCountry?.code
prefs!!["carrier_countryiso"] = mSelectedCountry?.iso
prefs!!["country_prefix"] = mSelectedCountry?.prefix
Timber.d("No Item selected on spinner : code ${mSelectedCountry?.code}, iso ${mSelectedCountry?.iso}, prefix ${mSelectedCountry?.prefix}")
mEditText!!.setText(mSelectedCountry?.prefix)
mEditText!!.setSelection(mSelectedCountry?.prefix!!.length+1)
}
}
Now I expect to be able to use the spinner listener even after the edited text has been focused.
The code you've posted works as expected.
Can you please create a very simple project and add this line to that project and check if everything works properly? If below code works in your simple project we can debug your main project further. If this is not working, then there could be a problem in your device.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:background="#mipmap/ic_launcher"
android:layout_marginBottom="10dp" android:layout_marginTop="10dp">
<androidx.appcompat.widget.AppCompatSpinner
android:layout_width="wrap_content"
android:layout_height="match_parent" android:id="#+id/spinnerCountries"
android:spinnerMode="dropdown" android:layout_margin="5dp"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#android:color/white"/>
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/input_layout_phone"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#android:color/holo_orange_dark">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/input_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="phone"
android:hint="phone number"
android:importantForAutofill="noExcludeDescendants"
android:maxLength="20"
android:drawableRight="#mipmap/ic_launcher"
android:textColor="#android:color/holo_orange_dark"
tools:ignore="UnusedAttribute" android:background="#null" android:fitsSystemWindows="true"/>
</com.google.android.material.textfield.TextInputLayout>
</FrameLayout>
</LinearLayout>
MainActivity.kt
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, Arrays.asList("a","b","c"))
spinnerCountries.adapter =adapter
spinnerCountries!!.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(arg0: AdapterView<*>, arg1: View, position: Int, arg3: Long) {
input_phone!!.text!!.clear()
input_phone!!.text!!.clearSpans()
input_phone!!.setText(adapter.getItem(position))
input_phone!!.setSelection(adapter?.getItem(position)!!.length)
}
override fun onNothingSelected(arg0: AdapterView<*>) {
}
}
}
}