I have a problem with RecyclerView.
When I fill my descTextView to my adapter file. DescTextView Scrool is not working. I want to scrool just text in descTextView.
If i change layout_height to match_parent in item_detail_view.xml then all pages starts to scroll. But I dont want it.
Here is my codes. What is wrong
Sometimes scroll is working and lost how is work I dont know.
I tried some codes bu I dont find the problem.
//fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="56dp"
android:layout_marginTop="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
//And This is HomeFragment Codes
package com.example.mybottomapplication.ui.home
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import com.example.mybottomapplication.databinding.FragmentHomeBinding
import android.widget.Toast
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import android.util.Log
import androidx.recyclerview.widget.GridLayoutManager
import androidx.appcompat.app.AppCompatActivity
class HomeFragment : Fragment(), CategoryAdapter.OnItemClickListener, ProductAdapter.OnProductClickListener {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private var isShowingProducts = false
private var isShowingProductDetail = false
private var categories: List<CategoryData> = emptyList()
private var products: List<ProductData> = emptyList()
private var productDetails: List<ProductDetailData> = emptyList()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
// RecyclerView'i bağla ve ayarla
setupRecyclerView()
val token = PreferenceHelper.getToken(requireContext())
if (token != null) {
loadCategories(token)
} else {
Toast.makeText(requireContext(), "Token is not available", Toast.LENGTH_LONG).show()
}
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (isShowingProductDetail) {
showProducts()
} else if (isShowingProducts) {
showCategories()
} else {
isEnabled = false
requireActivity().onBackPressed()
}
}
})
return root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun setupRecyclerView() {
binding.recyclerView.layoutManager = GridLayoutManager(context, 2) // Default olarak iki sütunlu GridLayoutManager
binding.recyclerView.addItemDecoration(GridSpacingItemDecoration(2, 16, true)) // 16dp aralık, kenar dahil
}
private fun loadCategories(token: String) {
RetrofitClient.instance.getCategories(token).enqueue(object : Callback<CategoryResponse> {
override fun onResponse(call: Call<CategoryResponse>, response: Response<CategoryResponse>) {
if (response.isSuccessful) {
val categoryResponse = response.body()
if (categoryResponse != null && categoryResponse.success) {
categories = categoryResponse.data.filter { it.parent_id != "0" }
val adapter = CategoryAdapter(requireContext(), categories, this@HomeFragment)
binding.recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
(activity as AppCompatActivity).supportActionBar?.title = "Katalog" // Set initial header text
} else {
Log.e("CategoryResponse", "Response is unsuccessful or empty")
}
} else {
Log.e("CategoryResponse", "Failed to load categories: ${response.message()}")
Toast.makeText(requireContext(), "Failed to load categories", Toast.LENGTH_SHORT).show()
}
}
override fun onFailure(call: Call<CategoryResponse>, t: Throwable) {
Log.e("CategoryResponse", "Request failed: ${t.message}")
Toast.makeText(requireContext(), "Request failed: ${t.message}", Toast.LENGTH_SHORT).show()
}
})
}
override fun onItemClicked(categoryId: String, categoryName: String) {
val token = PreferenceHelper.getToken(requireContext())
if (token != null) {
loadProducts(token, categoryId)
(activity as AppCompatActivity).supportActionBar?.title = categoryName // Update header text with category name
isShowingProducts = true
} else {
Toast.makeText(requireContext(), "Token is not available", Toast.LENGTH_LONG).show()
}
}
private fun loadProducts(token: String, categoryId: String) {
RetrofitClient.instance.getProducts(token, categoryId).enqueue(object : Callback<ProductResponse> {
override fun onResponse(call: Call<ProductResponse>, response: Response<ProductResponse>) {
if (response.isSuccessful) {
val productResponse = response.body()
if (productResponse != null && productResponse.success) {
products = productResponse.data
val adapter = ProductAdapter(requireContext(), products, this@HomeFragment) // Here passing context and listener
binding.recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
} else {
Log.e("ProductResponse", "Response is unsuccessful or empty")
}
} else {
Log.e("ProductResponse", "Failed to load products: ${response.message()}")
Toast.makeText(requireContext(), "Failed to load products", Toast.LENGTH_SHORT).show()
}
}
override fun onFailure(call: Call<ProductResponse>, t: Throwable) {
Log.e("ProductResponse", "Request failed: ${t.message}")
Toast.makeText(requireContext(), "Request failed: ${t.message}", Toast.LENGTH_SHORT).show()
}
})
}
private fun loadProductDetails(token: String, productId: String) {
RetrofitClient.instance.getProductDetails(token, productId).enqueue(object : Callback<ProductDetailResponse> {
override fun onResponse(call: Call<ProductDetailResponse>, response: Response<ProductDetailResponse>) {
if (response.isSuccessful) {
val productDetailResponse = response.body()
if (productDetailResponse != null && productDetailResponse.success) {
productDetails = productDetailResponse.data
val adapter = ProductDetailAdapter(requireContext(), productDetails)
binding.recyclerView.layoutManager = GridLayoutManager(context, 1) // Tek sütunlu GridLayoutManager
binding.recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
} else {
Log.e("ProductDetailResponse", "Response is unsuccessful or empty")
}
} else {
Log.e("ProductDetailResponse", "Failed to load product details: ${response.message()}")
Toast.makeText(requireContext(), "Failed to load product details", Toast.LENGTH_SHORT).show()
}
}
override fun onFailure(call: Call<ProductDetailResponse>, t: Throwable) {
Log.e("ProductDetailResponse", "Request failed: ${t.message}")
Toast.makeText(requireContext(), "Request failed: ${t.message}", Toast.LENGTH_SHORT).show()
}
})
}
override fun onProductClicked(productId: String, productName: String) {
val token = PreferenceHelper.getToken(requireContext())
if (token != null) {
loadProductDetails(token, productId)
(activity as AppCompatActivity).supportActionBar?.title = productName // Update header text with product name
isShowingProductDetail = true
} else {
Toast.makeText(requireContext(), "Token is not available", Toast.LENGTH_LONG).show()
}
}
fun isShowingProducts(): Boolean {
return isShowingProducts
}
fun isShowingProductDetail(): Boolean {
return isShowingProductDetail
}
fun showCategories() {
val adapter = CategoryAdapter(requireContext(), categories, this)
binding.recyclerView.layoutManager = GridLayoutManager(context, 2) // İki sütunlu GridLayoutManager
binding.recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
(activity as AppCompatActivity).supportActionBar?.title = "Katalog" // Reset header text
isShowingProducts = false
isShowingProductDetail = false
}
fun showProducts() {
val adapter = ProductAdapter(requireContext(), products, this)
binding.recyclerView.layoutManager = GridLayoutManager(context, 2) // İki sütunlu GridLayoutManager
binding.recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
(activity as AppCompatActivity).supportActionBar?.title = "Ürünler" // Reset header text
isShowingProducts = true
isShowingProductDetail = false
}
}
//And Adapter Codes are here
package com.example.mybottomapplication.ui.home
import android.content.Context
import android.text.Html
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.mybottomapplication.R
import android.text.method.ScrollingMovementMethod
class ProductDetailAdapter(private val context: Context, private val products: List<ProductDetailData>) : RecyclerView.Adapter<ProductDetailAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_product_detail, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val product = products[position]
holder.nameTextView.text = product.ProductName
holder.productId = product.ProductId
holder.descTextView.text = Html.fromHtml(product.Details, Html.FROM_HTML_MODE_LEGACY)
holder.descTextView.movementMethod = ScrollingMovementMethod()
Glide.with(holder.itemView.context)
.load("https://domain/${product.ImageUrls[0].Small}")
.into(holder.imageView)
// Sekmelerin tıklama olayları
holder.tab1.setOnClickListener {
holder.descTextView.text = Html.fromHtml(product.Details, Html.FROM_HTML_MODE_LEGACY)
}
holder.tab2.setOnClickListener {
holder.descTextView.text = Html.fromHtml(product.Additional5, Html.FROM_HTML_MODE_LEGACY) // Tab2 için Additional5 verisi
}
holder.tab3.setOnClickListener {
holder.descTextView.text = Html.fromHtml(product.Additional1, Html.FROM_HTML_MODE_LEGACY) // Tab3 için Additional1 verisi
}
}
override fun getItemCount(): Int {
return products.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val nameTextView: TextView = itemView.findViewById(R.id.nameTextView)
val descTextView: TextView = itemView.findViewById(R.id.descTextView)
val imageView: ImageView = itemView.findViewById(R.id.imageView)
val tab1: TextView = itemView.findViewById(R.id.tab1)
val tab2: TextView = itemView.findViewById(R.id.tab2)
val tab3: TextView = itemView.findViewById(R.id.tab3)
var productId: String? = null
}
}
//And item_activity_detail.xml
androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
android:background="@drawable/category_item_background">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="200dp"
android:scaleType="fitCenter"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/nameTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="8dp"
android:textColor="@android:color/black"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/imageView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<LinearLayout
android:id="@+id/tabLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3"
app:layout_constraintTop_toBottomOf="@id/nameTextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:id="@+id/tab1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/tab_background_selector"
android:clickable="true"
android:gravity="center"
android:padding="8dp"
android:text="1"
android:textColor="@android:color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/tab2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/tab_background_selector"
android:clickable="true"
android:gravity="center"
android:padding="8dp"
android:text="2"
android:textColor="@android:color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/tab3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/tab_background_selector"
android:clickable="true"
android:gravity="center"
android:padding="8dp"
android:text="3"
android:textColor="@android:color/black"
android:textSize="16sp" />
</LinearLayout>
<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:fillViewport="true"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tabLayout">
<TextView
android:id="@+id/descTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:textColor="@android:color/black"
android:textSize="16sp" />
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
I tried nestedScrollview and using to textview scrolls I cant work healty
Hakan ÖZGÜR is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.