RecyclerView flickering line while scrolling - android

I'm working on my first Android app and implemented a RecyclerView to scroll through some items.
I followed the following Youtube Tutorial.
I'm using a Huawei P20 Pro (physical device) to test the program, and i noticed that there is a flickering line while scrolling through the items. (On the emulator, use a Google Pixel 3 and there is no noticeable flickering)
White flickering line that appears during scrolling
I implemented the adapter as:
package com.example.recyclerviewexample
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.test_3.R
import kotlinx.android.synthetic.main.example_item.view.*
class ExampleAdapter(private val exampleList: List<ExampleItem>) : RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExampleViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(
R.layout.example_item,
parent,
false)
return ExampleViewHolder(itemView)
}
override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {
val currentItem = exampleList[position]
holder.imageView.setImageResource(currentItem.imageResource)
holder.textView1.text = currentItem.text1
holder.textView2.text = currentItem.text2
}
override fun getItemCount() = exampleList.size
class ExampleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.image_view //image_view is the id of the image! (same: itemView.findViewById(R.id.image_view))
val textView1: TextView = itemView.text_view_1
val textView2: TextView = itemView.text_view_2
}
}
Also, i uploaded my code to Github so you can try it out yourself.
As I'm very new to android studio, I really have no clue what's going on and would highly appreciate your help.
Thanks :)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context=".MaliActivity">
<include
android:id="#+id/toolbar_main"
layout="#layout/toolbar_mali"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_below="#+id/toolbar_main"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/search_list"
android:layout_width="399dp"
android:layout_height="633dp"
android:layout_below="#+id/searchView"
android:layout_margin="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
<androidx.appcompat.widget.SearchView
android:id="#+id/searchView"
android:layout_width="331dp"
android:layout_height="53dp"
android:layout_alignParentRight="true"
android:padding="10dp"
app:queryHint="Search for a resource ">
</androidx.appcompat.widget.SearchView>
</RelativeLayout>

Check out the Layout file. the match_parent on the Layout height property. Change it to wrap_content.
In my case the issue was each item in the recyclerview occupied the whole screen and this helped. It could be the same for you.

Related

RECYCLE VIEW onBindFucntion not working as I am following and learnign through a tuitorial

So i have been following this tuitorial and for soem reason I can not import my text from xml to kotlin file.
I have tried diffrent things but it still wont work.
I did add id 'kotlin-android-extensions' to my gradle:module:app but still wot go though.
Here is my code
todoAdapter.kt
`
package com.example.todo
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.recyclerview.widget.RecyclerView
class todoAdapter(
private val todos : MutableList<Todo>
):RecyclerView.Adapter<todoAdapter.TodoViewHolder>() {
class TodoViewHolder(itemView:View): RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_todo,parent,false);
return TodoViewHolder(view);
}
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
val curTodo = todos[position]
holder.itemView.tv (this bracket is not included in the code, the reason i onyl wrote tv is that if i wrote full it would be a red text and not get thr refrence)
}
override fun getItemCount(): Int {
return todos.size;
}
}
`
item_todo.xml
`
<?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"
android:layout_width="match_parent"
android:layout_height="70dp"
android:paddingStart="14dp"
android:paddingEnd="14dp">
<TextView
android:id="#+id/tvTodoTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Example"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="#+id/tvCheckboxTodo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
`
I have tried using the apply but that funciton too doesnt seem to work , I just wanna know where I am doing htinsg wrong. Please expalin begnier level as I am still lenring
I think you meant to do this:
class TodoViewHolder(itemView:View): RecyclerView.ViewHolder(itemView) {
val tvTodoTitle: TextView = itemView.findViewById(R.id.tvTodoTitle)
val tvCheckboxTodo: Checkbox = itemView.findViewById(R.id.tvCheckboxTodo)
}
Then in your onBindViewHolder you can do
holder.tvTodoTitle.text = "Whatever you want"
You must create the reference first then you can call it later. You can create tvTodoTitle in the body of class TodoViewHolder by the following code:
TextView tvTodoTitle = itemView.findViewById(R.id.tvTodoTitle);
then in onBindViewHolder you can call the tvTodoTitle reference:
holder.itemView.tvTodoTitle ...

why am i getting this error "Unresolved reference: titleView" and Variable expected for text instead every thing is as expected

I checked code many time but could not find any error also updated android to latest version but this also not worked on the following line:
holder.titleView.text=item[position]
here's my kotlin code:
NewsAdapter.kt
package com.example.newsapp
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class NewsAdapter(private val item: ArrayList<String>):RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val v=LayoutInflater.from(parent.context).inflate(R.layout.item,parent,false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val currItem=item[position]
holder.titleView.text=item[position]
}
override fun getItemCount(): Int {
return item.size
}
}
class ViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
val titleView: TextView=itemView.findViewById(R.id.titleView)
}
item.xml code:
<?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"
android:layout_margin="10dp">
<TextView
android:id="#+id/titleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Your holder is an instance of RecyclerView.ViewHolder, you must inherit your Adapter class for your own ViewHolder class that you define below the Adapter class already; something like this:
class NewsAdapter(private val item: ArrayList<String>): RecyclerView.Adapter<ViewHolder>()

RecyclerView functions aren't called

I am trying to show a list of transactions in a recycler view.
Each transaction is represented by a CardView inside a constraint layout (see item_transaction.xml).
Somehow, the functions of my RecyclerView Adapter (onCreateViewHolder, onBindViewHolder and getItemCount) are never called (logs are never displayed - I removed most of them so the code is easier to read).
Therefore, the RecyclerView content doesn't display on my app.
It is also worth pointing out that I have a list of transactions called data in my adapter. Whenever I set the data in the list, it does update. No issues there.
💡 I know notifyDataSetChanged() isn't clean, I'll change it later on when I manage to get everything working.
Here is a preview of what I want so you can grasp the idea better :
EDIT : My fragment displays normally and has no problem executing code.
Hang on tight because there is a lot of code :
package com.example.manage.manageit.database
class Transaction(
var value: Long = 0,
var note: String = "",
var budget: String = "",
var creationTime: Long = System.currentTimeMillis()
)
Transaction.kt
package com.example.manage.manageit.home
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.manage.manageit.databinding.ActivityHomeBinding
import androidx.fragment.app.Fragment
import com.example.manage.manageit.R
import com.example.manage.manageit.about.AboutFragment
import com.example.manage.manageit.budget.TransactionFragment
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHomeBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_home)
binding.bottomNavigation.menu.getItem(0).isCheckable = true
setFragment(HomeFragment())
binding.bottomNavigation.setOnItemSelectedListener {menu ->
when(menu.itemId){
R.id.homeFragmentButton -> {
setFragment(HomeFragment())
true
}
R.id.transactionFragmentButton -> {
setFragment(TransactionFragment())
true
}
R.id.aboutFragmentButton -> {
setFragment(AboutFragment())
true
}
else -> false
}
}
}
private fun setFragment(fr : Fragment){
val frag = supportFragmentManager.beginTransaction()
frag.replace(R.id.myNavHostFragment,fr)
frag.commit()
}
}
HomeActivity.kt : It contains a BottomNavigationView and my fragment.
package com.example.manage.manageit.home
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.manage.manageit.R
import com.example.manage.manageit.adapters.TransactionAdapter
import com.example.manage.manageit.database.Transaction
import com.example.manage.manageit.databinding.FragmentHomeBinding
import java.util.logging.Logger
class HomeFragment : Fragment() {
private var logger = Logger.getLogger(HomeFragment::class.java.name)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding: FragmentHomeBinding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_home,
container,
false
)
val recyclerView: RecyclerView = binding.transactionList
val transactionAdapter = TransactionAdapter()
recyclerView.adapter = transactionAdapter
recyclerView.layoutManager = LinearLayoutManager(context)
transactionAdapter.data = listOf(
Transaction(10, "Transaction note", "Groceries"),
Transaction(20, "Transaction note", "Groceries"),
Transaction(30, "Transaction note", "Groceries")
)
return inflater.inflate(R.layout.fragment_home, container, false)
}
}
HomeFragment.kt
package com.example.manage.manageit.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.manage.manageit.R
import com.example.manage.manageit.database.Transaction
import java.util.logging.Logger
class TransactionAdapter : RecyclerView.Adapter<TransactionViewHolder>() {
private var logger = Logger.getLogger(this::class.java.name)
var data = listOf<Transaction>()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder {
logger.info("adapter : onCreateViewHolder()")
return TransactionViewHolder.from(parent)
}
override fun onBindViewHolder(holder: TransactionViewHolder, position: Int) {
val item = this.data[position]
holder.bind(item)
}
override fun getItemCount(): Int {
logger.info("adapter : getItemCount()")
return this.data.size
}
}
class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val icon: ImageView = itemView.findViewById(R.id.transaction_icon)
private val note: TextView = itemView.findViewById(R.id.transaction_note)
private val value: TextView = itemView.findViewById(R.id.transaction_value)
fun bind(item: Transaction) {
icon.setImageResource(R.drawable.ic_dollar_sign)
note.text = item.note
value.text = item.value.toString()
}
companion object {
fun from(parent: ViewGroup): TransactionViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater
.inflate(R.layout.item_transaction, parent, false)
return TransactionViewHolder(view)
}
}
}
TransactionAdapter.kt
<?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"
tools:context="com.example.manage.manageit.home.HomeActivity">
<RelativeLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/myNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"/>
</LinearLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#android:color/black"
android:paddingVertical="6dp"
app:itemIconSize="28dp"
app:itemIconTint="#color/nav_bar_item"
app:itemRippleColor="#color/ripple_color"
app:itemTextColor="#color/nav_bar_item"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/bottom_navigation_menu" />
</RelativeLayout>
</layout>
activity_home.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"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:fillViewport="true"
tools:context="com.example.manage.manageit.home.HomeFragment">
<TextView
android:id="#+id/homeActivityTitle"
style="#style/activityTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/medium_margin"
android:layout_marginTop="#dimen/medium_margin"
android:layout_marginEnd="#dimen/medium_margin"
android:text="#string/home_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/transaction_list"
android:layout_width="match_parent"
android:layout_height="400dp"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="#+id/floatingActionButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/homeActivityTitle" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="#dimen/medium_margin"
android:layout_marginBottom="#dimen/very_big_margin"
android:backgroundTint="#color/secondaryColor"
android:clickable="true"
android:contentDescription="#string/add_button_description"
android:src="#drawable/ic_plus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:maxImageSize="32dp"
tools:ignore="RedundantDescriptionCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
fragment_home.xml
<?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="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
app:cardBackgroundColor="#android:color/transparent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/transaction">
<ImageView
android:id="#+id/transaction_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:contentDescription="Icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_dollar_sign"
app:tint="#android:color/white" />
<TextView
android:id="#+id/transaction_note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:text="Transaction note"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/transaction_icon"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/transaction_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="30dp"
android:text="55€"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
item_transaction.xml : Basically a card view with an image and two text views (the transaction "note" and value).
In onCreateView, you have created your view layout twice. The first one you did using DataBindingUtil and that's the one whose RecyclerView you set up. But then you let that whole layout go back to the garbage collector because you create a brand new layout using layoutInflater and return that layout on the last line of onCreateView.
Technically, you should not be setting up views in onCreateView anyway. It should be done in onViewCreated(), although I don't think it makes much difference. However, since Fragment provides a constructor that can automatically inflate a provided layout ID, I think it's cleaner anyway to eliminate onCreateView() entirely, like this:
class HomeFragment : Fragment(R.layout.fragment_home) {
private var logger = Logger.getLogger(HomeFragment::class.java.name)
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?
) {
val binding: FragmentHomeBinding = DataBindingUtil.bind(view)
val recyclerView: RecyclerView = binding.transactionList
val transactionAdapter = TransactionAdapter()
recyclerView.adapter = transactionAdapter
recyclerView.layoutManager = LinearLayoutManager(context)
transactionAdapter.data = listOf(
Transaction(10, "Transaction note", "Groceries"),
Transaction(20, "Transaction note", "Groceries"),
Transaction(30, "Transaction note", "Groceries")
)
}
}

DropDownTextView Android change color

I using https://github.com/hakobast/DropdownTextView in version 0.1.1
version 0.3.1 is not suitable for me.
I'm wondering if it any chance to change the frame colour when I click DropdownTextView.
The second thing is how can I move the DropdownTextView title to the centre?
As you can see I have all gravity in centre mode and nothing happens.
My code:
MainActivity.kt
package com.example.myapplication
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.*
import android.widget.*
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.google.gson.Gson
import hakobastvatsatryan.DropdownTextView
class MainActivity : AppCompatActivity()
{
#RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var zwrotkaString = """{
}"""
var stat:Statistic = Gson().fromJson(zwrotkaString, Statistic::class.java)
val d = findViewById<ListView>(R.id.first_dropdown_text_view_list)
d.adapter = MyCustomAdapter(this#MainActivity, stat);
}
private class MyCustomAdapter(context: Context, stat: Statistic): BaseAdapter()
{
val statS:Statistic
private val mContext: Context
init
{
mContext = context
}
init
{
statS = stat
}
override fun getCount(): Int {
return statS.statisticsForGroups.size;
}
override fun getItem(position: Int): Any
{
return statS.statisticsForGroups[position];
}
override fun getItemId(position: Int): Long
{
return position.toLong();
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View
{
val layoutInflater = LayoutInflater.from(mContext);
val rowMain = layoutInflater.inflate(R.layout.rowlistviewstatistic, parent, false)
val statDropDownText = rowMain.findViewById<DropdownTextView>(R.id.dropdowntextrow)
statDropDownText.setTitleText("Title")
statDropDownText.setContentText("Content")
return rowMain
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
tools:openDrawer="start"
android:layout_gravity="center"
android:gravity="center"
>
<ListView
android:id="#+id/first_dropdown_text_view_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#android:color/transparent"
android:dividerHeight="20sp"
android:scrollbarStyle="insideInset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewMain"
app:layout_constraintVertical_bias="0.403"
tools:ignore="MissingConstraints"
android:layout_gravity="center"
/>
</LinearLayout>
rowlistviewstatistic.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="qweqdasdasdasdadaq aa fadfeaeef"
/>
<hakobastvatsatryan.DropdownTextView
android:id="#+id/dropdowntextrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content_text_color="#color/purple_500"
app:arrow_drawable="#drawable/ic_arrow"
app:title_text_color="#color/colorRed"
android:layout_gravity="center"
android:gravity="center"
app:title_text_size="30sp"
app:bg_drawable_expanded="#drawable/answer_drawable"
android:clickable="true"
android:focusable="true"
/>
</LinearLayout>
answer_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#color/answer_border" />
<corners android:radius="5dp" />
</shape>
I'am wondering if it any chance to change frame color when I click DropdownTextView
Add OnClickListener to your TextView and once the user clicks it change the frame color
statDropDownText.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
statDropDownText.setRegularBackgroundDrawableRes(R.drawable.answer_drawable)
}
});
Second thing is how can I move DropdownTextView title to center ?
After going through the source code I found this method getTitleTextView().
Calling this will return the TextView, and set gravity to center.
TextView ta = (TextView) getTitleTextView();
LayoutParams lp = new LayoutParams();
lp.gravity = Gravity.CENTER_HORIZONTAL;
ta.setLayoutParams(lp);
I fixed the 0.3.1 crash and released 0.3.3 please try and let me know if it fixes your problem.
I am not the owner of the library I forked it and fixed the crash and have to release it on jitpack rather than bintray(jcentre) as it deprecated.
Please find the detail for integrating the library at
https://stackoverflow.com/a/67520594/4828650

(Android Kotlin) RecyclerView Adapter methods not called: empty RecyclerView being shown

I am trying to display JSON data from a dummy server (json-server) using Retrofit2 and display it in a RecyclerView placed inside a fragment. So far the following events are taking place (found out using Log infos):
Main fragment CharactersListFragment.kt creation is initiated.
Only getItemCount() is being called. It is returning 0.
OnCreateViewHolder() and onBindViewHolder() are not being called.
Data is successfully fetched from the server and passed to the adapter (from CharactersListFragment.kt)
There are no compile time errors nor does my app crash, just the RecyclerView is empty.
Here are my code files:
Layout for fragment with RecyclerView: fragment_characters_list.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".CharactersListFragment">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recycler_view"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Layout for RecyclerView row: fragment_character_recyclerview_list.xml
<?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/character_card_view"
android:layout_width="match_parent"
android:layout_height="300dp"
android:elevation="15dp"
app:cardBackgroundColor="#color/violet_forcard"
app:cardCornerRadius="3dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/char_thumnail_img"
android:layout_width="143dp"
android:layout_height="150dp"
android:layout_marginStart="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.106"
tools:srcCompat="#tools:sample/avatars" />
<TextView
android:id="#+id/char_id_txt"
android:layout_width="190dp"
android:layout_height="53dp"
android:layout_marginTop="16dp"
android:fontFamily="#font/roboto"
android:text="Character ID: "
android:textAlignment="viewStart"
android:textColor="#color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/char_thumnail_img"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/char_name_txt"
android:layout_width="190dp"
android:layout_height="53dp"
android:layout_marginTop="24dp"
android:fontFamily="#font/roboto"
android:text="Name: "
android:textAlignment="viewStart"
android:textColor="#color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/char_thumnail_img"
app:layout_constraintTop_toBottomOf="#+id/char_id_txt" />
<TextView
android:id="#+id/char_descp_txt"
android:layout_width="359dp"
android:layout_height="wrap_content"
android:fontFamily="#font/roboto"
android:textAlignment="viewStart"
android:textColor="#color/white"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.461"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.918" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Kotlin class for fragment: CharactersListFragment.kt
package com.example.marvelapp
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class CharactersListFragment : Fragment() {
private lateinit var charsAdapter: CharacterListAdapter
private lateinit var apiService: APIService
private var characters: MutableList<Character> = ArrayList()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
Log.i("INSIDE_FRAGMENT_ONCREATEVIEW", "Fragment creation initiated")
val v = inflater.inflate(R.layout.fragment_characters_list, container, false)
apiService = RestClient.client.create(APIService::class.java)
getCharacterList()
val recycler_view = v.findViewById(R.id.recycler_view) as RecyclerView
recycler_view.layoutManager = LinearLayoutManager(activity)
charsAdapter = CharacterListAdapter()
recycler_view.adapter = charsAdapter
return v
}
private fun getCharacterList(){
val call = apiService!!.get_characters()
call.enqueue(object: Callback<List<Character>> {
override fun onResponse(
call: Call<List<Character>>,
response: Response<List<Character>>
) {
val chars = response.body()
Log.i("get_character_succeeded_FOR_CALL", chars.toString())
if (chars != null){
characters.addAll(chars!!)
Log.i("character_ADD_CHECK_INSIDE_FRAGMENT", characters[0].toString())
charsAdapter.submitDataforcharList(characters)
}
}
override fun onFailure(call: Call<List<Character>>, t: Throwable) {
Log.e("get_character_failed", t.localizedMessage)
}
})
}
}
Kotlin class for adapter: CharacterListAdapter.kt
package com.example.marvelapp
import android.text.Layout
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.fragment_character_recyclerview_list.view.*
class CharacterListAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var charItems: List<Character> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
Log.i("INSIDE_ONCREATE_VIEWHOLDER", "reached")
return CharacterListViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.fragment_character_recyclerview_list,
parent,
false))
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder){
is CharacterListViewHolder ->{
Log.i("VIEWHOLDER_FOUND", "proceeding to bind")
holder.bind(charItems.get(position))
}
}
}
override fun getItemCount(): Int {
Log.i("INSIDE_ADAPTER_GET_ITEM_COUNT", charItems.size.toString())
return charItems.size
}
fun submitDataforcharList (characterlist: List<Character>){
Log.i("INSIDE_ADAPTER_SUBMIT_DATA", characterlist[0].toString())
charItems = characterlist
}
class CharacterListViewHolder
constructor(view: View): RecyclerView.ViewHolder(view){
val char_id = view.findViewById<TextView>(R.id.char_id_txt)
val char_name = view.findViewById<TextView>(R.id.char_name_txt)
val char_descp = view.findViewById<TextView>(R.id.char_descp_txt)
fun bind(character: Character){
Log.i("INSIDE_VIEWHOLDER_BIND", character.toString())
val id = Integer.toString(character.charId)
val id_mess = "Character ID: $id"
char_id.setText(id_mess)
val char_name_mess = "Name: ${character.charName}"
char_name.setText(char_name_mess)
char_descp.setText(character.charDescp)
}
}
}
the Character model class:
package com.example.marvelapp
data class Character(
val charId: Int,
val charName: String,
val charDescp: String,
){
}
I am an android beginner and have been stuck at this for quite some time, any help will be highly appreciated.
Thanks in advance!
In the onCreateView of CharactersListFragment you are calling getCharacterList() and then you move on with your initialization of the recycler view. After the getCharacterList call completes, you might be getting some data and you are simply updating the data list in your adapter class but you are not informing your recyclerview to refresh the view to display the new data. So I think if you just call notifyDataSetChanged() on your adapter after setting the new data it should work.
The other way to solve the issue could be if you initialize your recyclerview after you've received the data from the getCharacterList() call and just show some loading icon in place of the recycler view while the data is being fetched.
getCharacterList() is called on UI thread (main thread) but communicating (requests and responses) between device and API server is happening in another thread, it means there is no guarantee that onResponse() will come earlier than recycler_view.adapter = charsAdapter and in reality, it mostly does not happens. Therefor, you must call charsAdapter.notifyDataSetChanged() after charsAdapter.submitDataforcharList(characters) to have the recyclerview represent data. Another more elegent way to do that is adding notifyDatasetChanged() inside submitDataforcharList():
fun submitDataforcharList (characterlist: List<Character>){
charItems = characterlist
notifyDatasetChanged()
}

Categories

Resources