Android Studio 3.6
I want to use ViewPager2 to swipe images:
here xml layout:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/waitressCallMainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolBarContainer"
layout="#layout/tool_bar"
android:title='#{#string/articles}'
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPager2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#bbccaa"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolBarContainer" />
here adapter item layout (article_item_tour.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:id="#+id/imageTourPageMainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/tourArticleImageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
here my custom adapter:
class MyAdapter : RecyclerView.Adapter<MyAdapter .ArticleViewHolder>() {
var articleList: List<Article> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
return ArticleViewHolder(parent)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(articleList[position], position)
}
fun setList(articleList: List<Article>) {
this.articleList = articleList
notifyDataSetChanged()
}
override fun getItemCount(): Int = articleList.size
class MyViewHolderconstructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
constructor(parent: ViewGroup) :
this(
LayoutInflater.from(parent.context).inflate(
R.layout.article_item_tour,
parent,
false
)
)
fun bind(article: Article, number: Int) {
Glide.with(itemView.tourArticleImageView.getContext())
.load("http://www.gravatar.com/avatar/$number?s=200x200&d=identicon")
.apply(RequestOptions().error(R.drawable.default_image))
.into(itemView.tourArticleImageView)
}
}
}
And here result:
As you can see the ViewPager2 success swipe 2 images. Nice.
but I want to set height of viewpager = 300 dp. I'm not need to show image at whole screen.
So here changes:
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPager2"
android:layout_width="0dp"
android:layout_height="300dp"
android:background="#bbccaa"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolBarContainer" />
But now images not show. Show only ViewPager2 (green background). And as result no swipe.
I found solution:
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPager2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#bbccaa"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolBarContainer" />
and in article_item_tour_xml
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/imageTourPageMainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/tourArticleImageView"
android:layout_width="0dp"
android:layout_height="300dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
And here result:
Related
I have horizontal recycler view in which each child has nested scroll view in which I have another horizontal recycler view. View seems to bo displaying fine but I am not able to scroll child recycler view. When I am trying to scroll - parent recycler view is scrolling, which is not what I want. Already was trying to set android:nestedScrollingEnabled="false” but it’s not working.
Main view 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=".views.home.WeatherView">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_WeatherRecycler"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/pb_WeatherLoading"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Parent recycler view item 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:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
app:cardCornerRadius="40dp"
app:cardElevation="5dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="#drawable/ic_location">
<ImageView
android:id="#+id/iv_CityImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
tools:srcCompat="#tools:sample/avatars"
/>
<androidx.core.widget.NestedScrollView
android:id="#+id/sv_ScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
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="match_parent">
<ImageView
android:id="#+id/iv_LocationIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintEnd_toStartOf="#+id/tv_CityName"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_location" />
<TextView
android:id="#+id/tv_CityName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="#+id/iv_LocationIcon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/iv_LocationIcon"
app:layout_constraintTop_toTopOf="#+id/iv_LocationIcon" />
<TextView
android:id="#+id/tv_CurrentTemp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="400dp"
android:text="TextView"
android:textSize="48sp"
app:layout_constraintBottom_toTopOf="#+id/tv_CurrentWeatherDesc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/iv_LocationIcon"
app:layout_constraintVertical_chainStyle="spread" />
<TextView
android:id="#+id/tv_CurrentWeatherDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="#+id/tv_SunriseLabel"
app:layout_constraintEnd_toEndOf="#+id/tv_CurrentTemp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/tv_CurrentTemp"
app:layout_constraintTop_toBottomOf="#+id/tv_CurrentTemp" />
<TextView
android:id="#+id/tv_SunriseLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Sunrise"
app:layout_constraintBottom_toTopOf="#+id/tv_SunsetLabel"
app:layout_constraintEnd_toStartOf="#+id/tv_SunriseValue"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_CurrentWeatherDesc" />
<TextView
android:id="#+id/tv_SunsetLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"
android:text="Sunset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/tv_SunsetValue"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_SunriseLabel" />
<TextView
android:id="#+id/tv_SunriseValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="SunriseVal"
app:layout_constraintBaseline_toBaselineOf="#+id/tv_SunriseLabel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/tv_SunriseLabel" />
<TextView
android:id="#+id/tv_SunsetValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="SunsetVal"
app:layout_constraintBaseline_toBaselineOf="#+id/tv_SunsetLabel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/tv_SunsetLabel" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_HourlyForecastRecycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="32dp"
android:scrollbars="horizontal|vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_SunsetLabel" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Child item 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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardCornerRadius="10dp"
app:cardElevation="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_HourlyForecast_Time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toTopOf="#+id/iv_ForecastHourly_WeatherIcon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/iv_ForecastHourly_WeatherIcon"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="#+id/tv_HourlyForecast_Temp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_HourlyForecast_Time"
app:srcCompat="#drawable/ic_error" />
<TextView
android:id="#+id/tv_HourlyForecast_Temp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/iv_ForecastHourly_WeatherIcon" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Main view code:
#AndroidEntryPoint
class WeatherView : Fragment() {
private var _binding: FragmentWeatherViewBinding? = null
private val binding: FragmentWeatherViewBinding get() = _binding!!
private val viewModel by viewModels<WeatherViewModel>()
private lateinit var weatherAdapter: WeatherAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentWeatherViewBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val cities = getSavedCitiesFromFirebase()
viewModel.getWeatherAndImageForCities(cities)
setupRecyclerView()
observeWeatherData()
}
private fun observeWeatherData() {
viewModel.citiesLoadingLiveData.observe(viewLifecycleOwner, { isLoading ->
if (isLoading) {
showLoading(true)
} else {
showLoading(false)
}
})
viewModel.citiesDataLiveData.observe(viewLifecycleOwner, { cities ->
if (cities != null) {
weatherAdapter.setCities(cities)
}
})
viewModel.cityFetchErrorLiveData.observe(viewLifecycleOwner, {
/* To Do */
})
}
private fun setupRecyclerView() {
weatherAdapter = WeatherAdapter()
binding.rvWeatherRecycler.apply {
layoutManager = LinearLayoutManager(
requireContext(), RecyclerView.HORIZONTAL, false
)
adapter = weatherAdapter
}
}
private fun showLoading(isLoading: Boolean) {
binding.pbWeatherLoading.visibility = if (isLoading) View.VISIBLE else View.GONE
}
private fun getSavedCitiesFromFirebase(): List<String> {
return listOf("Berlin", "Amsterdam")
}
}
Parent recycler view adapter code:
class WeatherAdapter: RecyclerView.Adapter<WeatherAdapter.WeatherViewHolder>() {
private var cities: MutableList<CityData> = mutableListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherViewHolder {
val itemBinding = ItemWeatherBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return WeatherViewHolder(itemBinding.root, itemBinding)
}
override fun onBindViewHolder(holder: WeatherViewHolder, position: Int) {
holder.bind(cities[position])
}
override fun getItemCount(): Int {
return cities.size
}
fun setCities(newCities: List<CityData>) {
cities.clear()
cities.addAll(newCities)
notifyDataSetChanged()
}
class WeatherViewHolder(private val itemView: View, private val itemBinding: ItemWeatherBinding): RecyclerView.ViewHolder(itemBinding.root) {
fun bind(item: CityData) {
itemBinding.rvHourlyForecastRecycler.apply {
layoutManager = LinearLayoutManager(
itemView.context, RecyclerView.HORIZONTAL, false
)
adapter = HourlyForecastAdapter(item.forecastModel.list)
setHasFixedSize(true)
}
itemBinding.tvCityName.text = item.weatherModel.name
itemBinding.tvCurrentTemp.text = TemperatureConverter.convertKelvinToCelsius(item.weatherModel.main.temp).toString()
itemBinding.tvCurrentWeatherDesc.text = item.weatherModel.weather[0].description
itemBinding.tvSunriseValue.text = TimeConverter.convertTime(item.weatherModel.sys.sunrise)
itemBinding.tvSunsetValue.text = TimeConverter.convertTime(item.weatherModel.sys.sunset)
Glide
.with(itemBinding.ivCityImage)
.load(item.cityImg)
.error(R.drawable.ic_error)
.centerCrop()
.into(itemBinding.ivCityImage)
}
}
}
Child recycler view adapter code:
class HourlyForecastAdapter(private val forecast: List<WeatherForecast>): RecyclerView.Adapter<HourlyForecastAdapter.HourlyForecastViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HourlyForecastViewHolder {
val itemBinding = ItemWeatherHourlyForecastBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return HourlyForecastViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: HourlyForecastViewHolder, position: Int) {
holder.bind(forecast[position])
}
override fun getItemCount(): Int {
return forecast.size
}
class HourlyForecastViewHolder(private val itemBinding: ItemWeatherHourlyForecastBinding): RecyclerView.ViewHolder(itemBinding.root) {
fun bind(item: WeatherForecast) {
Timber.d("DT: ${item.dt}")
itemBinding.tvHourlyForecastTime.text = TimeConverter.convertTime(item.dt.toInt())
itemBinding.tvHourlyForecastTemp.text = TemperatureConverter.convertKelvinToCelsius(item.main.temp).toString()
Glide
.with(itemBinding.ivForecastHourlyWeatherIcon)
.load("https://openweathermap.org/img/wn/${item.weather[0].icon}#2x.png")
.error(R.drawable.ic_error)
.centerCrop()
.into(itemBinding.ivForecastHourlyWeatherIcon)
}
}
}
I have a list that load in RecyclerView with CardView and in CardView I have a RecyclerView that have (max) 10 items, I load it now, but it has lag:
My First LessonContentListAdapter.kt:
class LessonContentListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var onItemClickListener: ((LessonsContentList) -> Unit)? = null
fun setOnItemClickListener(listener: (LessonsContentList) -> Unit) {
onItemClickListener = listener
}
private val callback = object : DiffUtil.ItemCallback<LessonsContentList>() {
override fun areItemsTheSame(
oldItem: LessonsContentList,
newItem: LessonsContentList
): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(
oldItem: LessonsContentList,
newItem: LessonsContentList
): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, callback)
override fun getItemCount(): Int {
return differ.currentList.size
}
inner class LessonContentListItems(private val lessonContentListItemsBinding: LessonContentListItemsBinding) :
RecyclerView.ViewHolder(lessonContentListItemsBinding.root) {
fun bind(lessons: LessonsContentList) {
lessonContentListItemsBinding.txtContentTitleO.text = lessons.titleOriginal
lessonContentListItemsBinding.txtContentTitleT.text = lessons.titleTranslate
lessonContentListItemsBinding.txtTime.text = lessons.timeLaps
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view =
LessonContentListItemsBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return LessonContentListItems(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as LessonContentListItems).bind(differ.currentList[position])
val childLessonContentListVectorsAdapter =
ChildLessonContentListVectorsAdapter(
differ.currentList[position].imgLevels
)
holder.itemView.recyclerLessonsContentListVectors.layoutManager = LinearLayoutManager(
holder.itemView.recyclerLessonsContentListVectors.context,
LinearLayoutManager.HORIZONTAL,
false
)
holder.itemView.recyclerLessonsContentListVectors.setHasFixedSize(true)
holder.itemView.recyclerLessonsContentListVectors.adapter =
childLessonContentListVectorsAdapter
}
}
Second ChildLessonContentListVectorsAdapter.kt:
class ChildLessonContentListVectorsAdapter(imgLevels: List<ImgLevelsDetalis>) :
RecyclerView.Adapter<ChildLessonContentListVectorsAdapter.MyViewHolder>() {
var childModelArrayList: List<ImgLevelsDetalis> = imgLevels
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var heroImage: ImageView
init {
heroImage = itemView.findViewById(R.id.imgHaveStudied)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.child_lessons_content_list, parent, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem: ImgLevelsDetalis = childModelArrayList[position]
holder.heroImage.setImageResource(currentItem.img)
}
override fun getItemCount(): Int {
return childModelArrayList.size
}
}
First fragment_lesson_content_list.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"
android:background="#color/white"
android:clickable="true"
android:fitsSystemWindows="true"
android:focusable="true"
tools:context=".presentation.ui.lessoncontentlist.LessonContentListFragment">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbarLessonContentList"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/purple_500"
android:contentInsetStart="0dp"
android:contentInsetLeft="0dp"
android:minHeight="?attr/actionBarSize"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<ImageButton
android:id="#+id/imgBackContent"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:background="#null"
android:paddingLeft="10dp"
android:src="#drawable/ic_baseline_arrow_back_24" />
<TextView
android:id="#+id/txtTitleContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textColor="#color/white"
android:textStyle="bold" />
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerLessonsContentList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbarLessonContentList" />
</androidx.constraintlayout.widget.ConstraintLayout>
second lesson_content_list_items.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
card_view:cardBackgroundColor="#color/purple_700"
card_view:cardCornerRadius="4dp"
card_view:layout_constraintLeft_toLeftOf="parent"
card_view:layout_constraintRight_toRightOf="parent"
card_view:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:weightSum="10">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="5"
android:orientation="horizontal"
android:weightSum="10">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="8"
android:orientation="vertical">
<TextView
android:id="#+id/txtContentTitleO"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Grammer"
android:textColor="#color/white"
android:textStyle="bold" />
<TextView
android:id="#+id/txtContentTitleT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="مکالمه"
android:textColor="#color/white" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="right"
android:orientation="horizontal">
<TextView
android:id="#+id/txtTime"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:text="2Min"
android:textColor="#color/white"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:adjustViewBounds="true"
android:scaleType="center"
android:src="#drawable/ic_baseline_timelapse_24" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="right"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerLessonsContentListVectors"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:orientation="horizontal" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Third child_lessons_content_list.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="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right">
<ImageView
android:id="#+id/imgHaveStudied"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Firstly, you can use setInitialItemPrefetchCount() for a prefetching feature for nested RecyclerView. for more information please check this article
I think, the main reason, loading images from the server blocks the main thread. You can do this asynchronously. please check this article too.
So hello, I have a little problem here.
I can't implement my binding properly into adapter for RecycleView. I need it to display my products in cart as you can see in the code below. I am a beginner with adapter, so please help me.
CartItemsListAdapter.kt *here is where I want to implement binding*
class CartItemsListAdapter(
private val context: Context,
private var list: ArrayList<CartItem>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
RecyclerView.ViewHolder {
return MyViewHolder(
LayoutInflater.from(context).inflate(
R.layout.item_cart_layout,
parent,
false
)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val model = list[position]
if (holder is MyViewHolder) {
Glide.with(context)
.load(model.image)
.placeholder(R.drawable.ic_launcher)
.into(/*binding.ivCartItemImage*/)
//binding.tvCartItemPrice.text = model.price
//binding.tvCartItemTitle.text = model.title
}
}
override fun getItemCount(): Int {
return list.size
}
private class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
activity_cart_list.xml *xml file for reference and from where I want to take those bindings*
<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=".ui.activities.CartListActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar_cart_list_activity"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="?attr/colorSecondary">
<ImageView
android:id="#+id/arrow_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_arrow_left"
android:hapticFeedbackEnabled="true"
android:layout_marginTop="16sp"
android:padding="24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_gravity="top"
android:contentDescription="#string/back_button" />
<com.example.trieskask.utils.OswaldBold
android:id="#+id/tv_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="My cart"
android:textSize="26sp"
android:elevation="3dp"
android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_cart_items_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="#id/ll_checkout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar_cart_list_activity" />
<com.example.trieskask.utils.OswaldRegular
android:id="#+id/tv_no_cart_item_found"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="No cart item found!"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="#id/ll_checkout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar_cart_list_activity" />
<LinearLayout
android:id="#+id/ll_checkout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSecondary"
android:elevation="4dp"
android:orientation="vertical"
android:padding="16dp"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.trieskask.utils.OswaldLight
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Subtotal:" />
<com.example.trieskask.utils.OswaldLight
android:id="#+id/tv_sub_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="$100" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.trieskask.utils.OswaldLight
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Shipping charge:" />
<com.example.trieskask.utils.OswaldLight
android:id="#+id/tv_shipping_charge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="$10" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.trieskask.utils.OswaldBold
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Total Amount" />
<com.example.trieskask.utils.OswaldBold
android:id="#+id/tv_total_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="$110" />
</LinearLayout>
<com.example.trieskask.utils.OswaldButton
android:id="#+id/btn_checkout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="16dp"
android:background="#drawable/btn_ripple_effect"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:text="Checkoutt"
android:textColor="#android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Thanks for any kind of help
You can refactor your MyViewHolder class to require an ActivityCartListBinding as a constructor argument. Then your onCreateViewHolder function will look like:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ActivityCartListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyViewHolder(binding)
}
And finally your onBindViewHolder:
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int
) {
val model = list[position]
if (holder is MyViewHolder) {
Glide.with(context)
.load(model.image)
.placeholder(R.drawable.ic_launcher)
.into(/*binding.ivCartItemImage*/)
holder.getBinding().tvCartItemPrice.text = model.price
holder.getBinding().tvCartItemTitle.text = model.title
}
}
View Holder
private class MyViewHolder(val binding: ActivityCartListBinding) : RecyclerView.ViewHolder(binding.root)
This should solve your issue.
I am developing a new app but image view not showing inside card view I want to know exactly where I am making a mistake
below my layout
<?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:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/cardview"
android:layout_width="match_parent"
android:layout_height="93dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/companyLogo"
android:layout_width="45dp"
android:layout_height="26dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="11dp"
android:layout_marginRight="11dp"
android:padding="4dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toTopOf="#+id/companyWebsite"
app:layout_constraintEnd_toStartOf="#+id/companyName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="#+id/companyWebsite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="56dp"
android:layout_marginLeft="56dp"
android:layout_marginTop="40dp"
android:text="Company Website"
android:textSize="8sp"
app:layout_constraintBottom_toBottomOf="#id/companyLogo"
app:layout_constraintStart_toStartOf="#+id/companyLogo"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/companyName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginEnd="286dp"
android:layout_marginRight="286dp"
android:text="Company Name"
android:textSize="8sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/companyLogo"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
My current UI from the real device:
below my RecyclerviewAdapter class where I have downloaded image view using glide and implemented ImageView logic
below my RecyclerviewAdapter class where I have downloaded image view using glide and implemented ImageView logic
class SpectrumAdapter(
private val spectrumResponse: ArrayList <SpectrumResponseItem>
) : RecyclerView.Adapter<SpectrumViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SpectrumViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.spectrum_list, parent, false)
return SpectrumViewHolder(view)
}
override fun getItemCount(): Int {
return spectrumResponse.size
}
override fun onBindViewHolder(holder: SpectrumViewHolder, position: Int) {
return holder.bind(spectrumResponse[position])
}
}
class SpectrumViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val companyLogo: ImageView = itemView.findViewById(R.id.companyLogo)
private val companyName: TextView = itemView.findViewById(R.id.companyName)
private val companyWebsite: TextView = itemView.findViewById(R.id.companyWebsite)
fun bind(spectrum: SpectrumResponseItem) {
Glide.with(itemView.context).load(spectrum.logo).into(companyLogo)
companyName.text = spectrum.company
companyWebsite.text = spectrum.website
}
}
In my project, I have used RecyclerView which is shown in layout-preview as I expected but the problem is when I run the application in emulator/device the items of RecyclerView not showing as layout-preview shown.
Here is the XML of recyclerview.
<?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=".view.LActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/rv_sample" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
android:src="#drawable/ic_add"
android:id="#+id/fabAdd"
app:tint="#color/white"
app:backgroundTint="#color/colorPrimary"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
XML of recyclerview items.
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
app:cardCornerRadius="10dp"
android:minHeight="60dp"
app:cardUseCompatPadding="true"
app:strokeColor="#color/design_default_color_secondary_variant"
app:strokeWidth="1dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_gravity="center"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvWord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="10dp"
android:drawableStart="#drawable/arrow_right"
android:fontFamily="monospace"
android:text="#{item.word}"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tvType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{item.type}"
android:layout_marginEnd="10dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#id/tvWord" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
Adapter class
class MyAdapter(private var itemList: List<Item>, private val listener: ItemClickListener) :
RecyclerView.Adapter<MyAdapter.VHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = RvSampleBinding.inflate(inflater)
return VHolder(binding)
}
override fun getItemCount(): Int = itemList.size
override fun onBindViewHolder(holder: VHolder, position: Int) = holder.bind(itemList[position])
inner class VHolder(private val binding: RvSampleBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: Item) {
binding.item = item
binding.root.setOnClickListener {
listener.onItemClick(item)
}
binding.executePendingBindings()
}
}
Screenshot of layout-preview
And Screenshot of actual output.
I have run the application in several emulators and devices but can't figure out where is the problem.
Here I am going to answer my own question. So that this answer will help other users who will face same issue.
Thanks, #MikeM for his helpful comment. All credit goes to him.
Problem: The problem is in my adapter, I was inflating the item-layout without the parent viewgroup passed.
Cause: If you don't pass the parent in your layout-inflater that will inflate your layout with default layout-params and that wrap your content in both directions(width and height), even though you might have match_parent for the layout_width.
in my case, I have tried like this
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = RvSampleBinding.inflate(inflater) // here i didn't pass viewgroup and boolean parameters.
return VHolder(binding)
}
Solution: My problem is solved by modifying the onCreateViewHolder like the following.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = RvSampleBinding.inflate(inflater,parent,false) //here i have passed viewgroup and boolean parameter and that's solve my problem
return VHolder(binding)
}
So basically your parent Layout is constraint layout, so you have to add all constraint related to all the views, One suggestion just used another parent layout instead of Constraint layout just for the check/validation purpose.
<?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=".RecyclerViewActivity"
android:id="#+id/recyclerView_ex1">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/recycler_view_item_ex1" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
android:src="#drawable/ic_add"
android:id="#+id/fabAdd"
app:tint="#color/cardview_light_background"
app:backgroundTint="#color/colorPrimary"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
app:layout_constraintRight_toRightOf="parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
itemview
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tool="http://schemas.android.com/tools"
android:padding="5dp"
app:cardCornerRadius="10dp"
android:minHeight="60dp"
app:cardUseCompatPadding="true"
app:strokeColor="#color/colorAccent"
app:strokeWidth="1dp"
xmlns:android="http://schemas.android.com/apk/res/android"
tool:context=".RecyclerViewActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_gravity="center"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tvWord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="10dp"
android:drawableStart="#drawable/arrow_right"
android:fontFamily="monospace"
android:text="word"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/tvType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="type"
android:layout_marginEnd="10dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#id/tvWord"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
Please vote if it works.
Happy coding. Thanks