Why is the RecyclerView loading before the rest Kotlin Android - java

Hello I am doing a little app for my homework and I want to display data from my php api on the app. But the Recycler View send this message 2022-04-25 00:41:36.662 13593-13593/net.robcorp.finalapp E/RecyclerView: No adapter attached; skipping layout before the adapter code runs because this message 2022-04-25 00:41:36.907 13593-13593/net.robcorp.finalapp I/System.out: [Drivers(pos=1, name=Charles Leclerc, nb=16, points=71, title=Ferrari), Drivers(pos=2, name=Esteban Ocon, nb=31, points=20, title=Alpine)] is displayed after the previous one and is suppose to run just before the adapter.
Here is the DriversFragment.kt:
package net.robcorp.finalapp
import android.content.Context
import android.graphics.Insets.add
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.core.view.OneShotPreDrawListener.add
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import net.robcorp.finalapp.R
import net.robcorp.finalapp.databinding.FragmentDriversBinding
import net.robcorp.finalapp.drivers.DriverFragmentAdapter
import net.robcorp.finalapp.drivers.Drivers
import org.json.JSONArray
class DriversFragment : Fragment(R.layout.fragment_drivers) {
private lateinit var recyclerView: RecyclerView
private lateinit var myAdapter: DriverFragmentAdapter;
lateinit var binding: FragmentDriversBinding
private val drivers = ArrayList<Drivers>()
val url = "https://robcorp.net/f1api/getdrivers.php"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentDriversBinding.inflate(layoutInflater)
recyclerView = binding.driversRecyclerView
recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
myAdapter = DriverFragmentAdapter(drivers)
recyclerView.adapter = myAdapter
println("adapter loaded")
downloadDrivers()
}
fun downloadDrivers() {
val task = Volley.newRequestQueue(this.context)
val request = StringRequest(Request.Method.GET, url, {
response ->
val data = response.toString()
val jArray = JSONArray(data)
// Log.e("Error",response.toString())
for (i in 0..jArray.length()-1) {
val json_data = jArray.getJSONObject(i)
// Log.e("Jobject",json_data.toString())
val pos = i+1
val name = json_data.getString("Name")
val nb = json_data.getString("NB")
val points = json_data.getString("Points")
val title = json_data.getString("Title")
val driver = Drivers(pos, name, nb, points, title)
drivers.add(driver)
}
println(drivers)
myAdapter.notifyDataSetChanged()
}, {
error ->
println(error)
})
task.add(request)
}
}
Here is the DriverFragmentAdapter.kt:
package net.robcorp.finalapp.drivers
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import net.robcorp.finalapp.R
import net.robcorp.finalapp.databinding.DriverListBinding
class DriverFragmentAdapter(private var driversList: List<Drivers>): RecyclerView.Adapter<DriverFragmentAdapter.MyViewHolder>() {
class MyViewHolder(val binding: DriverListBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(driver: Drivers) {
val context = itemView.context
val pos = itemView.findViewById<TextView>(R.id.driver_position)
val bar = itemView.findViewById<TextView>(R.id.driver_bar)
val name = itemView.findViewById<TextView>(R.id.driver_name)
val nb = itemView.findViewById<TextView>(R.id.driver_number)
val team = itemView.findViewById<TextView>(R.id.driver_team)
val points = itemView.findViewById<TextView>(R.id.driver_points)
pos.text = driver.pos.toString()
name.text = driver.name
nb.text = driver.nb
team.text = driver.title
points.text = driver.points
if (driver.title == "Ferrari") {
bar.background = ContextCompat.getDrawable(context, R.drawable.ferrari_bar)
} else if (driver.title == "Alpine") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alpine_bar)
} else if (driver.title == "Red Bull") {
bar.background = ContextCompat.getDrawable(context, R.drawable.redbull_bar)
} else if (driver.title == "Mercedes") {
bar.background = ContextCompat.getDrawable(context, R.drawable.mercedes_bar)
} else if (driver.title == "McLaren") {
bar.background = ContextCompat.getDrawable(context, R.drawable.mclaren_bar)
} else if (driver.title == "Alfa Romeo") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alfaromeo_bar)
} else if (driver.title == "AlphaTauri") {
bar.background = ContextCompat.getDrawable(context, R.drawable.alphatauri_bar)
} else if (driver.title == "Williams") {
bar.background = ContextCompat.getDrawable(context, R.drawable.williams_bar)
} else if (driver.title == "Aston Martin") {
bar.background = ContextCompat.getDrawable(context, R.drawable.astonmartin_bar)
} else if (driver.title == "Haas") {
bar.background = ContextCompat.getDrawable(context, R.drawable.haas_bar)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(DriverListBinding.inflate(LayoutInflater.from(parent.context)))
}
override fun getItemCount(): Int {
return driversList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val driver = driversList[position]
holder.binding.apply {
println("je suis dans le binding")
holder.bind(driver)
}
}
fun setDriversList(driversList: List<Drivers>) {
this.driversList = driversList
notifyDataSetChanged()
}
}
fragment_drivers.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="match_parent"
tools:context=".MainActivity">
<!-- TODO: Update blank fragment layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="10dp">
<TextView
android:id="#+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="20dp"
android:fontFamily="#font/marianneb"
android:text="Pilotes"
android:textAlignment="center"
android:textColor="#color/white"
android:textSize="25sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/drivers_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#+id/header"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
driver_list.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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:elevation="8dp"
android:orientation="horizontal"
android:padding="10dp"
android:background="#drawable/rectangle">
<TextView
android:id="#+id/driver_position"
android:layout_width="30dp"
android:layout_height="match_parent"
android:fontFamily="#font/marianneb"
android:text="1"
android:textColor="#color/black"
android:textSize="25sp"
android:textAlignment="center"/>
<ImageView
android:id="#+id/driver_bar"
android:layout_width="20px"
android:layout_height="match_parent"
android:background="#drawable/ferrari_bar"/>
<LinearLayout
android:layout_width="250dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/driver_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fontFamily="#font/marianneb"
android:text="Charles Leclerc"
android:textColor="#color/black"
android:textSize="15sp"
android:layout_marginStart="10dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/driver_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="2.5dp"
android:fontFamily="#font/mariannem"
android:text="16"
android:textColor="#color/black"
android:textSize="10sp" />
<TextView
android:id="#+id/driver_team"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="2.5dp"
android:fontFamily="#font/mariannem"
android:text="Ferrari"
android:textColor="#color/black"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/driver_points"
android:layout_width="50dp"
android:layout_height="match_parent"
android:fontFamily="#font/marianneb"
android:text="578"
android:textColor="#color/black"
android:textSize="25sp"/>
</LinearLayout>

It’s a harmless warning. Since your RecyclerView is already in the layout, it attempts to draw it the moment your view hierarchy becomes visible, sees that there is no adapter assigned, and so it just issues the warning and doesn’t draw it.
Perhaps it would be cleaner to create your adapter (with an empty list) and assign it immediately upon inflating the view, and just update its list when the data is ready.
By the way, it is incorrect to inflate your layout in onCreate. That should be done in onCreateView.
Edit:
Your code here is inflating the layout twice, once for the variable v, and once for the binding property. First of all, there's no reason to inflate it twice. Secondly, since you use v as the return value of onCreateView, anything you do to the views in the binding is pointless and has no effect on the views that are actually on screen.
val v = inflater.inflate(R.layout.fragment_drivers, container, false)
binding = FragmentDriversBinding.inflate(layoutInflater)
// ...
return v
You should only inflate the view once (using the binding) and return the binding's view:
// DELETE THIS LINE: val v = inflater.inflate(R.layout.fragment_drivers, container, false)
binding = FragmentDriversBinding.inflate(layoutInflater)
// ...
return binding.root
Also, it is more proper to set up your views in onViewCreated() instead of in onCreateView(). And if you do that, you actually can move inflation into the super-constructor call by passing the view ID to the Fragment constructor, and then instead of inflating your binding, you bind to the existing view. It would look like this:
class DriversFragment : Fragment(R.layout.fragment_drivers) {
private lateinit var recyclerView: RecyclerView
private lateinit var myAdapter: DriverFragmentAdapter;
lateinit var binding: FragmentDriversBinding
private val drivers = ArrayList<Drivers>()
val url = "https://robcorp.net/f1api/getdrivers.php"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentDriversBinding.bind(view)
recyclerView = binding.driversRecyclerView
recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
myAdapter = DriverFragmentAdapter(drivers)
recyclerView.adapter = myAdapter
println("adapter loaded")
downloadDrivers()
}
//...
}

To add a little bit of clarity to #Tenfour04 's answer.
You can't remove this. They are telling you how to properly inflate it with viewbinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentDriversBinding.inflate(layoutInflater, container, false)
return binding.root
}
also a little side note:
You should destroy your binding like so to prevent memory leaks
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
Now to the question.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//binding = FragmentDriversBinding.bind(view) this is not needed since its already been inflated
//recyclerView = binding.driversRecyclerView why keep recyclerview as another variable when you can access it with binding.driversRecyclerView?
binding.driversRecyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
myAdapter = DriverFragmentAdapter(drivers)
binding.driversRecyclerView.adapter = myAdapter
println("adapter loaded")
downloadDrivers()
}
Finally the issue is most likely your layout.
Since everything is wrapped inside a linear layout, the constraint layouts position lines don't do anything.
I removed the useless linear layout.
Hopefully this fixes any issues.
sorry about the formatting btw just use CTRL + ALT + L to auto format it
<?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"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="10dp">
<TextView
android:id="#+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="20dp"
android:fontFamily="#font/marianneb"
android:text="Pilotes"
android:textAlignment="center"
android:textColor="#color/white"
android:textSize="25sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/drivers_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#+id/header"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Related

How to change visibility of textview on button click without providing ID to them?

In this I need to know that how do I access a view without providing the Id to them in this there will be no id provided in any of the file. Without the use of external libraries like viewbinding, databinding, Butterknife etc
You can do that by using a combination of DataBinding, LiveData and ViewModel.
Read more about Data Binding: https://developer.android.com/topic/libraries/data-binding
You can enable Data Binding by putting this code in the module's gradle file under android section like this.
android {
buildFeatures {
dataBinding true
}
}
In Short
First: You need a LiveData for the values you want to inject in the view and a function to modify it, like this ViewModel
class MainViewModel : ViewModel() {
private val _isVisible: MutableLiveData<Boolean> = MutableLiveData<Boolean>(true)
val isVisible
get() = Transformations.map(_isVisible) {
when (it) {
true -> View.VISIBLE
else -> View.INVISIBLE
}
}
fun changeVisibility() {
_isVisible.value = !_isVisible.value!!
}
}
Second: You need to modify your layout to use our ViewModel by wrapping it in a element contains element like this, then simply you can call the variable and functions you need.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MyFragment">
<data>
<variable
name="MainViewModel"
type="hazem.projects.testing.ui.main.MainViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textview_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some Cool Text"
android:visibility="#{MainViewModel.isVisible}" />
<Button
android:id="#+id/button_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="#{()-> MainViewModel.changeVisibility()}"
android:text="Change Visibility" />
</LinearLayout>
</layout>
Third: You need to modify the fragment to use DataBinding.
this can be done by:
replacing the normal layout inflator with our binding object.
assign the ViewModel to the binding object
assign our fragment as a lifecycleOwner
class MainFragment : Fragment() {
private lateinit var binding: MainFragmentBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.main_fragment, container, false)
val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
binding.mainViewModel = viewModel
binding.lifecycleOwner = this
return binding.root
}
}
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
TextView txtView;
ConstraintLayout lay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// lay = ;
// Log.d("classname", "" + lay);
// Log.d("childcount", "" + lay.getChildCount());
//
}
public void click(View view) {
Log.d("getparent", "" + view.getParent());
lay = (ConstraintLayout) view.getParent();
lay.getChildAt(0).setVisibility(View.INVISIBLE);
txtView = (TextView) lay.getChildAt(0);
view.setOnLongClickListener(view1 -> {
txtView.setText("Hi");
txtView.setVisibility(View.VISIBLE);
return true;
});
}
}
activity_main.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="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="248dp"
android:text="Button"
android:onClick="click"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

onCreateView holder is getting called Multiple times and view is not getting updated

The problem is When data refreshes view is not getting updated.
My findings-
1. onCreateview is getting called multiple times, so multiple binder objects are there
2. I checked the list, updated list is reaching to the adapter
3. Data inserted in the db is correct.
4. I have atttached all the code snippets related to this
5. I have used sqaureup library for calendar
package com.universal.best.habittracker.view
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import `androidx.databinding.DataBindingUtil`
import androidx.fragment.app.*
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.universal.best.habittracker.R
import com.universal.best.habittracker.databinding.ActivityMainBinding
import com.universal.best.habittracker.repository.entity.ActivityEntityClass
import com.universal.best.habittracker.view.adapter.ActivityListAdapter
import com.universal.best.habittracker.view.adapter.ActivityStatusAdapter
import com.universal.best.habittracker.viewmodel.MainAcitivityViewModelProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.util.*
class MainActivity() : AppCompatActivity(),
AddActivityFinishInterface, ActivityAdapterEventrack {
lateinit private var mainActivityDataBinding: ActivityMainBinding
lateinit private var viewModel: MainAcitivityViewModelProvider;
val fragmentManager: FragmentManager = supportFragmentManager;
val tag:String="MainActivity"
companion object {
var newFragment: DialogFragment? = null
internal lateinit var context: Context
internal lateinit var mainActivityContext: Context
fun setContext(con: Context, mainActivityContextt: Context) {
context = con
mainActivityContext = mainActivityContextt
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainActivityDataBinding = DataBindingUtil.setContentView(
this,
R.layout.activity_main
);
setContext(
applicationContext, this
);
viewModel = ViewModelProvider(this).get(MainAcitivityViewModelProvider::class.java)
var handleCLick =
HandleCLick(
this,
fragmentManager, viewModel,
this
);
mainActivityDataBinding.clickHandler = handleCLick;
Log.d(tag,"Adapter created--")
var listAdapter = ActivityListAdapter(this);
Log.d(tag,"Adapter created with Hashcode--"+listAdapter.hashCode())
mainActivityDataBinding.listAdapter = listAdapter;
mainActivityDataBinding.recyclerView.adapter= listAdapter
mainActivityDataBinding.recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL ,false)
var statusAdapter = ActivityStatusAdapter();
mainActivityDataBinding.statusAdaptor = statusAdapter
mainActivityDataBinding.bottomRecylerView.setHasFixedSize(false);
viewModel.retreiveFromDb()
.observe(this, androidx.lifecycle.Observer { list ->
list?.let {
listAdapter.setAdapterData(list)
listAdapter.notifyDataSetChanged()
statusAdapter.setAdapter(list)
statusAdapter.notifyDataSetChanged()
}
})
viewModel.getSaveres()?.observe(this, androidx.lifecycle.Observer { viewModel.retreiveFromDb()
.observe(this, androidx.lifecycle.Observer { list ->
list?.let {
listAdapter.setAdapterData(list)
listAdapter.ListChangedSoCallNotify()
statusAdapter.clear()
statusAdapter.setAdapter(list)
statusAdapter.notifyDataSetChanged()
}
})
})
}
class HandleCLick(
val context: Context,
val fragmentManager: FragmentManager, val viewmodel: MainAcitivityViewModelProvider,
val addActivityFinishInterface: AddActivityFinishInterface
) {
fun onClick(view: View) {
when (view.id) {
R.id.imageView -> {
newFragment =
AddActivityDialogueFragment(
addActivityFinishInterface
)
newFragment?.show(fragmentManager, "dialog")
};
else -> {
Toast.makeText(context, "Invalid Input", Toast.LENGTH_SHORT).show()
};
}
}
}
#Override
override fun clickHandler(activtyName: String, list: ArrayList<Date>?) {
Toast.makeText(this, activtyName, Toast.LENGTH_SHORT).show()
newFragment?.dismiss()
var len: Int = list?.size ?: 0
when {
len == 1 -> {
Toast.makeText(this, "Valid date range selected ", Toast.LENGTH_SHORT)
.show()
list?.let {
viewModel.saveintoDB(activtyName, list.get(0), list.get(len - 1), "0") }
}
else -> Toast.makeText(this, "Valid date range not selected ", Toast.LENGTH_SHORT)
.show()
}
}
#Override
override fun onDestroy() {
super.onDestroy()
viewModel.close();
}
override fun deleteTriggered(model: ActivityEntityClass) {
viewModel.deleteEntityFromDB(model)
}
override fun viewChartTriggered() {
}
override fun imageCharTriggered() {
}
Above is my mainActivity
myAdapterClass
package com.universal.best.habittracker.view.adapter
import android.app.AlertDialog
import android.content.DialogInterface
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.universal.best.habittracker.R
import com.universal.best.habittracker.databinding.TopActivitiesItemLayoutBinding
import com.universal.best.habittracker.repository.entity.ActivityEntityClass
import com.universal.best.habittracker.view.ActivityAdapterEventrack
import com.universal.best.habittracker.view.MainActivity
import com.universal.best.habittracker.view.MainActivity.Companion.context
import com.universal.best.habittracker.view.MainActivity.Companion.mainActivityContext
class ActivityListAdapter(var adaptercallBackInterface: ActivityAdapterEventrack) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var list: List<ActivityEntityClass>? = null
val tag: String = "ActivityListAdapter"
lateinit var myViewHolder: MyViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater =LayoutInflater.from(parent.context)
val databinder = TopActivitiesItemLayoutBinding.inflate(inflater);
Log.d(tag, "onCreate dataBinder--" + databinder.hashCode());
myViewHolder = MyViewHolder(databinder);
Log.d(tag, "onCreate viewholder--" + myViewHolder.hashCode());
var Handler = MyClickHandler(adaptercallBackInterface)
databinder.myclickHanlder = Handler
return myViewHolder;
}
override fun getItemCount(): Int {
return list?.size ?: 0
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
myViewHolder.bindData(list, position);
}
override fun getItemViewType(position: Int): Int {
return position
}
fun setAdapterData(list: List<ActivityEntityClass>?) {
this.list = list
}
class MyViewHolder( databinder: TopActivitiesItemLayoutBinding) :
RecyclerView.ViewHolder(databinder.root) {
val databinderr: TopActivitiesItemLayoutBinding = databinder
fun bindData(
list: List<ActivityEntityClass>?,
i: Int
) {
databinderr.model = list?.get(i)
databinderr.executePendingBindings()
}
}
class MyClickHandler(var eventrack: ActivityAdapterEventrack) {
fun onclick(view: View, entityClass: ActivityEntityClass) {
when (view.id) {
R.id.imageView2 -> {
//open dialogbox and on yes delete it from db..
val dialogClickListener =
DialogInterface.OnClickListener { dialog, which ->
when (which) {
DialogInterface.BUTTON_POSITIVE -> {
Toast.makeText(
MainActivity.mainActivityContext,
"Activity name is ${entityClass.activityName}",
Toast.LENGTH_SHORT
).show()
eventrack.deleteTriggered(entityClass)
}
DialogInterface.BUTTON_NEGATIVE -> {
}
}
}
var builder: AlertDialog.Builder = AlertDialog.Builder(mainActivityContext)
builder.setMessage("Are you sure to delete this activity?")
.setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show()
}
R.id.imageView4 -> {
//open new actiivty with intent
}
}
}
}
fun ListChangedSoCallNotify() {
notifyDataSetChanged()
}
}
mainActivty 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>
<variable
name="clickHandler"
type="com.universal.best.habittracker.view.MainActivity.HandleCLick" />
<variable
name="listAdapter"
type="com.universal.best.habittracker.view.adapter.ActivityListAdapter" />
<variable
name="statusAdaptor"
type="com.universal.best.habittracker.view.adapter.ActivityStatusAdapter" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/homepage_bg"
tools:context=".view.Activity.MainActivity">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="48dp"
android:fontFamily="sans-serif-condensed"
android:text="Add New Habit to Track"
android:textColor="#FFFF"
android:textSize="#dimen/_18sdp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView"
android:layout_width="#dimen/_50sdp"
android:layout_height="#dimen/_50sdp"
android:layout_marginTop="28dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="#drawable/ic_add"
android:onClick="#{(view)->clickHandler.onClick(view)}"
app:layout_constraintBottom_toBottomOf="#+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.945"
app:layout_constraintStart_toEndOf="#+id/textView"
app:layout_constraintTop_toTopOf="#+id/textView"
app:layout_constraintVertical_bias="0.738" />
<TextView
android:id="#+id/notext"
android:layout_width="wrap_content"
android:layout_height="23dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView"
tools:text="You are not tracking any habbit" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="72dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/imageView"
tools:listitem="#layout/top_activities_item_layout" />
<TextView
android:id="#+id/textView3"
android:layout_width="149dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="40dp"
android:textColor="#FFFFFF"
android:textSize="#dimen/_18sdp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recyclerView"
android:text="Habbit Status" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/bottomRecylerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:adapter="#{statusAdaptor}"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView3"
app:layout_constraintVertical_bias="1.0"
tools:listitem="#layout/habit_staus_item" />
<TextView
android:textSize="#dimen/_14sdp"
android:textColor="#FFFF"
android:fontFamily="sans-serif-condensed"
android:id="#+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Select Other date"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.588"
app:layout_constraintStart_toEndOf="#+id/textView3"
app:layout_constraintTop_toTopOf="#+id/textView3" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
adapter 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>
<variable
name="model"
type="com.universal.best.habittracker.repository.entity.ActivityEntityClass" />
<variable
name="myclickHanlder"
type="com.universal.best.habittracker.view.adapter.ActivityListAdapter.MyClickHandler" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/itemview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent">
<TextView
android:id="#+id/Yoga"
android:layout_width="123dp"
android:layout_height="174dp"
android:background="#drawable/activity_item_background_color"
android:fontFamily="monospace"
android:gravity="center"
android:text="#{model.activityName}"
android:textColor="#FFFFFF"
android:textSize="#dimen/_30sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Yoga" />
<ImageView
android:onClick="#{(view)->myclickHanlder.onclick(view,model)}"
android:id="#+id/imageView2"
android:layout_width="#dimen/_70sdp"
android:layout_height="#dimen/_50sdp"
android:layout_marginTop="12dp"
android:layout_marginEnd="144dp"
android:layout_marginRight="144dp"
app:layout_constraintEnd_toEndOf="#+id/Yoga"
app:layout_constraintHorizontal_bias="0.294"
app:layout_constraintStart_toStartOf="#+id/Yoga"
app:layout_constraintTop_toBottomOf="#+id/Yoga"
app:srcCompat="#drawable/deleete" />
<ImageView
android:onClick="#{(view)->myclickHanlder.onclick(view,model)}"
android:id="#+id/imageView4"
android:layout_width="#dimen/_45sdp"
android:layout_height="#dimen/_45sdp"
android:layout_marginTop="#dimen/_10sdp"
app:layout_constraintEnd_toEndOf="#+id/Yoga"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="#+id/Yoga"
app:layout_constraintTop_toBottomOf="#+id/Yoga"
app:srcCompat="#drawable/chart" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
DataBindingUtil.setContentView() Utility class to create ViewDataBinding from layouts.
Base class for generated data binding classes. If possible, the
generated binding should be instantiated using one of its generated
static bind or inflate methods. If the specific binding is unknown,
bind(View) or inflate(LayoutInflater, int, ViewGroup, boolean) should
be used.
onCreateview() is getting called multiple times
You are using DataBinding. So kindly remove below.
setContentView(R.layout.activity_main)
Finally
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainActivityDataBinding = DataBindingUtil.setContentView(
this,
R.layout.activity_main
);

How to remove unwanted spaces between views added to a inflated LinearLayout?

I'm developing a android app to show some movies in a scrollable view with two columns.
Everything is okay except that I have huge space between rows.
I have tried many things that I found in StackOverflow, like: android:adjustViewBounds="true", set padding to zero and etc.
Can anyone give enlighten me?
Here is how the app is looking like
As you can see there is a huge space between rows
I'm adding the imageViews dynamically through inflate, and I think thats the issue.
Here is my code:
package com.example.androidvidly
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.squareup.picasso.Picasso
import org.json.JSONArray
import org.json.JSONObject
const val MOVIE_OBJECT_ID = "tokenlab.com.MOVIE_OBJECT_ID"
const val MOVIE_OBJECT_VOTES = "tokenlab.com.MOVIE_OBJECT_VOTES"
const val MOVIE_OBJECT_TITLE = "tokenlab.com.MOVIE_OBJECT_TITLE"
const val MOVIE_OBJECT_POSTER_URL = "tokenlab.com.MOVIE_OBJECT_POSTER_URL"
const val MOVIE_OBJECT_RELEASE_DATE = "tokenlab.com.MOVIE_OBJECT_RELEASE_DATE"
const val MOVIE_OBJECT_GENRES = "tokenlab.com.MOVIE_OBJECT_GENRES"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mQueue = Volley.newRequestQueue(this)
val url = "https://desafio-mobile.nyc3.digitaloceanspaces.com/movies" //API provided
//val url = "http://10.0.2.2:3000"// Node.js Backend
val gallery = findViewById<LinearLayout>(R.id.gallery)
val inflater = LayoutInflater.from(this)
var mAppName = findViewById<TextView>(R.id.appName)
mAppName.text="Vidly"
val gson = Gson()
var request = StringRequest(Request.Method.GET, url, Response.Listener { response ->
var moviesJSONArray = JSONArray(response)
for (i in 0 until moviesJSONArray.length()) {
var e : JSONObject = moviesJSONArray.getJSONObject(i)
//Initializing the object
val arrayStringType = object : TypeToken<ArrayList<String>>() {}.type
var genreListAux:ArrayList<String> = gson.fromJson(e.getString("genres"), arrayStringType)
var movieObject: Movie = Movie(e.getString("id").toInt(), e.getString("vote_average").toDouble(), e.getString("title"), e.getString("poster_url"), genreListAux, e.getString("release_date"))
if (i==0) {
var mImageView = findViewById<ImageView>(R.id.imageDisplay)
mImageView.setTag(movieObject)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
else if (i==1) {
var mImageView = findViewById<ImageView>(R.id.imageDisplay2)
mImageView.setTag(movieObject)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
else{
if(i.rem(2)==0) {
var view = inflater.inflate(R.layout.activity_main, gallery, false)
var mImageView = view.findViewById<ImageView>(R.id.imageDisplay)
mImageView.setTag(movieObject)
var height = gallery.height
view.minimumHeight=height
gallery.addView(view)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
else {
var view = gallery.getChildAt(gallery.childCount-1)
var mImageView = view.findViewById<ImageView>(R.id.imageDisplay2)
mImageView.setTag(movieObject)
loadImageFromUrl(movieObject.poster_url, mImageView)
mImageView.setPadding(0, 0, 0, 0);
}
}
}
}, Response.ErrorListener { error ->
error.printStackTrace()
})
mQueue.add(request)
}
fun showMore(view: View) {
val intent = Intent(this, MovieSelectedActivity::class.java).apply {
var movieObj : Movie = view.getTag() as Movie
putExtra(MOVIE_OBJECT_ID, movieObj.id)
putExtra(MOVIE_OBJECT_GENRES, movieObj.genres)
putExtra(MOVIE_OBJECT_POSTER_URL, movieObj.poster_url)
putExtra(MOVIE_OBJECT_RELEASE_DATE, movieObj.release_date)
putExtra(MOVIE_OBJECT_TITLE, movieObj.title)
putExtra(MOVIE_OBJECT_VOTES, movieObj.vote_average)
}
startActivity(intent)
}
fun loadImageFromUrl(url: String, mImageView: ImageView) {
Picasso.with(this).load(url).placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(
mImageView, null
)
}
}
Here is the xml for the views:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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="wrap_content"
android:layout_height="wrap_content"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/gallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background"
android:orientation="vertical"
android:weightSum="10"
android:adjustViewBounds="true">
<RelativeLayout
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true">
<TextView
android:id="#+id/appName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAppearance="#style/TextAppearance.AppCompat.Body2"
android:textColor="#000000"
android:textSize="60dp"
android:adjustViewBounds="true"/>
</RelativeLayout>
<RelativeLayout
android:layout_weight="8"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1"
android:layout_alignParentLeft="true"
android:adjustViewBounds="true">
<ImageView
android:id="#+id/imageDisplay"
android:layout_width="170dp"
android:layout_height="280dp"
android:clickable="true"
android:onClick="showMore"
android:adjustViewBounds="true"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1"
android:layout_alignParentRight="true"
android:adjustViewBounds="true">
<ImageView
android:id="#+id/imageDisplay2"
android:layout_width="170dp"
android:layout_height="280dp"
android:clickable="true"
android:onClick="showMore"
android:adjustViewBounds="true"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>
I Found out that the issue was with the background I was setting in the main linear layout. After removing it the huge spaces disappeared.
android:background="#drawable/background"

Kotlin RecyclerView with Multiple ViewHolders inside BottomSheet

I'm having troubles trying to display a recycler which contains more than 1 ViewHolder, i was testing and sending a custom List which contains only data to display a list of the 1st ViewType.
payments.add(Purchase(0,R.drawable.ic_cart,"",""))
payments.add(Purchase(0,R.drawable.ic_favorite,"",""))
payments.add(Purchase(0,R.drawable.ic_arrow_back,"",""))
This is the BottomSheetClass
class PaymentStepsFragment : SuperBottomSheetFragment() {
val payments = ArrayList<Any>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_steps_payment, container, false)
}
private fun RecyclerAnimator(recyclerView: RecyclerView, adapter: PurchaseViewAdapter) {
val itemAnimator = DefaultItemAnimator()
itemAnimator.addDuration = 1000
itemAnimator.removeDuration = 1000
recyclerView.itemAnimator = itemAnimator
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
payments.add(Purchase(0,R.drawable.ic_cart,"",""))
payments.add(Purchase(0,R.drawable.ic_favorite,"",""))
payments.add(Purchase(0,R.drawable.ic_arrow_back,"",""))
val recycler = view.findViewById<RecyclerView>(R.id.payment_rv)
val adapter = PurchaseViewAdapter(payments, context!!)
RecyclerAnimator(recycler, adapter)
}
override fun getCornerRadius() = context!!.resources.getDimension(R.dimen.sheet_rounded_corner)
override fun getStatusBarColor() = Color.RED
}
and my RecyclerViewAdapter.
constructor(list: List<Any>, context: Context) : this() {
this.list = list
this.context = context
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType){
0 -> {
context = parent.context
val menuItemLayoutView = LayoutInflater.from(parent.context).inflate(R.layout.fragment_card_payment, parent, false)
PaymentViewHolder(menuItemLayoutView)
}
else -> {
context = parent.context
val menuItemLayoutView = LayoutInflater.from(parent.context).inflate(R.layout.fragment_card_payment, parent, false)
PaymentViewHolder(menuItemLayoutView)
}
}
}
override fun getItemViewType(position: Int): Int {
val data = list?.get(position) as Purchase
return data.type
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder.itemViewType){
0 -> {
val holder_payment = holder as PaymentViewHolder
val menuItem = list!![position] as Purchase
holder_payment.paymentTimeline.marker = ContextCompat.getDrawable(context!!,menuItem.resource)
}
else -> {
val holder_payment = holder as PaymentViewHolder
val menuItem = list!![position] as Purchase
holder_payment.paymentTimeline.marker = ContextCompat.getDrawable(context!!,menuItem.resource)
}
}
}
However when I send the information to be displayed, it always return the list empty, I don't know where is the problem, the data it's seems to be sent nicely.
And the constructor of the RecyclerViewAdapter prints the List obtained, but that list won't display the DesiredViewHolders to be inflated in the RecyclerView...
As requested I added the Layout where I call the RecyclerView
<?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:id="#+id/view_bottom_sheet_attributes"
tools:background="#color/colorWhite">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="50dp"
android:id="#+id/text_attributes_heading"
android:gravity="center"
android:paddingLeft="12dp"
android:text="TEMPORAL"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<View
android:layout_width="0sp"
android:layout_height="1dp"
android:background="#color/colorDivider"
app:layout_constraintTop_toBottomOf="#id/text_attributes_heading"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/image_toggle"
android:layout_marginRight="5dp"
app:srcCompat="#drawable/ic_expand_less_black_24dp"
app:layout_constraintTop_toTopOf="#id/text_attributes_heading"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="#id/text_attributes_heading"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/payment_rv"
android:fillViewport="true"
android:padding="5dp"
android:clipToPadding="false"
app:layout_constraintTop_toBottomOf="#id/text_attributes_heading"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#id/button_apply">
</androidx.recyclerview.widget.RecyclerView>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#color/colorDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/payment_rv"/>
<com.google.android.material.button.MaterialButton
android:layout_width="match_parent"
android:layout_height="45dp"
android:id="#+id/button_apply"
android:layout_margin="5dp"
android:text="#string/purchase"
style="#style/Widget.MaterialComponents.Button"
android:insetTop="0dp"
android:insetBottom="0dp"
app:cornerRadius="0dp"
app:layout_constraintTop_toBottomOf="#id/payment_rv"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Also the type of the ViewHolder it seems that don't reach the override function...
Check your layout XML it looks like the RecyclerView view is hidden by other views

Drawer Scrolling Slowly

I have this drawer which opens normally but the scrolling in it is very slow, and I don't know why knowing that the image it has on top of it is not HD image, and available in the 4 sizes, I've done various examples in Java and it was fine, I wonder if the issue is that I'm using Kotlin in the adapter.
I would appreciate any help.
The activity's layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:fitsSystemWindows="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/gradient_background"
android:orientation="vertical">
<include
android:id="#+id/top"
layout="#layout/top_bar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize" />
<TextView
android:layout_below="#+id/top"
android:id="#+id/tvTradesTicker"
android:layout_width="match_parent"
android:layout_height="#dimen/trades_ticker_height"
android:background="#color/colorPrimaryLight"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:focusable="true"
android:freezesText="true"
android:marqueeRepeatLimit="marquee_forever"
android:padding="#dimen/small_margin"
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="#color/darkGray"
android:textSize="#dimen/font"
android:visibility="visible" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rvGrid"
android:layout_below="#+id/tvTradesTicker"
android:layout_above="#+id/llFooter"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
layout="#layout/footer"
android:id="#+id/llFooter"
android:layout_width="match_parent"
android:layout_height="#dimen/footer_height"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/white"
android:fitsSystemWindows="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:paddingTop="#dimen/big_margin_padding"
android:orientation="vertical">
<include
layout="#layout/item_drawer_header"
android:id="#+id/header"
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="#dimen/drawer_header_height" />
<ListView
android:id="#+id/lvItems"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white"
android:divider="#android:color/transparent"
android:paddingTop="#dimen/small_margin" />
</LinearLayout>
</android.support.design.widget.NavigationView>
The Drawer's Adapter:
class DrawerListAdapter : BaseAdapter {
private var drawerItems: MutableList<DrawerItem> = mutableListOf()
private var context: Context? = null
constructor(context: Context, notesList: MutableList<DrawerItem>) : super() {
this.drawerItems = notesList
this.context = context
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
val view: View?
val vh: ViewHolder
val inflater = LayoutInflater.from(context)
val type = getItemViewType(position)
if (convertView == null) {
view = if (type == 0){
inflater.inflate(R.layout.item_drawer_section, parent, false)
}else{
inflater.inflate(R.layout.item_drawer_child, parent, false)
}
vh = ViewHolder(view)
view.tag = vh
} else {
view = convertView
vh = view.tag as ViewHolder
}
val drawerItem = drawerItems[position]
vh.name.text = drawerItem.name
if (type == 0){
vh.rel.setBackgroundColor(ContextCompat.getColor(context!!, R.color.blue))
vh.name.setBackgroundColor(ContextCompat.getColor(context!!, R.color.colorAccent))
vh.name.setTextColor(ContextCompat.getColor(context!!, R.color.white))
}else if (type == 1){
vh.rel.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setTextColor(ContextCompat.getColor(context!!, R.color.colorPrimary))
vh.separator.visibility = View.VISIBLE
}else{
vh.rel.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setTextColor(ContextCompat.getColor(context!!, R.color.colorPrimary))
vh.separator.visibility = View.GONE
}
Actions.overrideFonts(context!!, vh.rel)
return view
}
override fun getItem(position: Int): DrawerItem {
return drawerItems[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return drawerItems.size
}
override fun getItemViewType(position: Int): Int {
if (drawerItems[position].isHeader)
return 0
else if (!drawerItems[position].isLast)
return 1
else
return 2
}
override fun getViewTypeCount(): Int {
return 3
}
}
private class ViewHolder(view: View) {
val rel: RelativeLayout = view.findViewById(R.id.rel) as RelativeLayout
val name: TextView = view.findViewById(R.id.name) as TextView
val separator = view.findViewById<View>(R.id.separator)
}
What should I change, the activity layout, or the adapter or what i realy have no idea.
EDIT
I set the visibility of the marquee text view in the layout to gone, and everything worked just fine, does anybody know why? because I don't want to replace this text view with a horizontal recycler view
SOLVED.
Changed the approach completely, I stopped the marquee and applied cross fade animation to the text view, with a handler that changes the object being set in the text view at each iteration, and now it looks perfect and way more elegnat

Categories

Resources