簡體   English   中英

回收站視圖不顯示

[英]Recycler view does not show

我有一個帶有網格布局的回收站視圖,它顯示帶有圖像、標題、描述和價格的卡片,但它沒有顯示任何內容。 數據已正確獲取,我假設布局文件中一定有錯誤,但我不知道它是什么。

這是片段代碼

package io.keepcoding.androidfinalproject.ui.products

import android.app.SearchManager
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.*
import android.widget.SearchView
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import io.keepcoding.androidfinalproject.R
import io.keepcoding.androidfinalproject.domain.Product
import io.keepcoding.androidfinalproject.repository.DataManager
import io.keepcoding.androidfinalproject.utils.CustomViewModelFactory
import io.keepcoding.androidfinalproject.utils.Status
import android.Manifest
import android.util.Log
import android.widget.Toast
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.GridLayoutManager
import io.keepcoding.androidfinalproject.ui.main.ClientActivity
import kotlinx.android.synthetic.main.fragment_products.*

/**
 * A simple [Fragment] subclass.
 * Use the [Products.newInstance] factory method to
 * create an instance of this fragment.
 */
class ProductsFragment : Fragment() {

    private val viewModel: ProductsFragmentViewModel by lazy {
        val factory = CustomViewModelFactory(requireActivity().application,
            DataManager())
        ViewModelProvider(this, factory).get(ProductsFragmentViewModel::class.java)
    }

    private val LOCATION_PERMISSION_REQUEST_CODE = 2000

    private var latitude: Double = 51.507351

    private var longitude: Double = -0.127759

    private var selectedRadius : Int = 1000

    private var productViewModels: List<Product>? = null

    private var productsAdapter: ProductsAdapter? = null

    var productsInteractionListener: ProductInteractionListener? = null

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is ProductInteractionListener){
            productsInteractionListener = context
        } else
            throw IllegalArgumentException("Context does not implement product interaction listener")
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_products, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        this.setUpRecyclerView()
        this.prepRequestLocationUpdates()
        this.fetchData()
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.products_search, menu)
        activity?.let { activity ->
            val searchViewItem = menu.findItem(R.id.action_search)
            val searchManager = activity.getSystemService(Context.SEARCH_SERVICE) as SearchManager
            val searchView = searchViewItem.actionView as SearchView
            searchView.queryHint = "Search products"
            searchView.setSearchableInfo(searchManager.getSearchableInfo(activity.componentName))
            searchView.isIconifiedByDefault = false
            searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {

                override fun onQueryTextSubmit(p0: String?): Boolean {
                    return false
                }

                override fun onQueryTextChange(newText: String?): Boolean {
                    var text = newText?.toLowerCase()
                    text?.let {
                        viewModel.searchProducts(selectedRadius, latitude, longitude, it)
                    }
                    return true
                }
            })
        }
        super.onCreateOptionsMenu(menu, inflater)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        selectedRadius = when(item.itemId) {
            R.id.one_radius -> 1000
            R.id.two_radius -> 2000
            R.id.three_radius -> 3000
            R.id.four_radius -> 4000
            else -> {
                5000
            }
        }
        return super.onOptionsItemSelected(item)
    }


    private fun setUpAdapter() {
        context?.let { context ->
            productsAdapter = ProductsAdapter(context) {
                this.productsInteractionListener?.goToProductDetail()
            }
            productViewModels?.let { products ->
                productsAdapter?.setData(products)
            }
        }
    }

    private fun setUpRecyclerView(){
        productsList.layoutManager = GridLayoutManager(context, 3)
        productsList.addItemDecoration(DividerItemDecoration(context, GridLayoutManager.VERTICAL))
    }

    private fun setUpObservers() {
        viewModel.getProducts().observe(viewLifecycleOwner, Observer { products ->
            when(products.status){
                Status.SUCCESS -> {
                    productViewModels = products.data
                    Log.    d("PRODUCTS", productViewModels.toString())
                    this.setUpAdapter()
                    productsList.visibility = View.VISIBLE
                    loadingView.visibility = View.INVISIBLE
                    retry.visibility = View.INVISIBLE
                }
                Status.LOADING -> {
                    productsList.visibility = View.INVISIBLE
                    loadingView.visibility = View.VISIBLE
                    retry.visibility = View.INVISIBLE
                }
                Status.ERROR -> {
                    productsList.visibility = View.INVISIBLE
                    loadingView.visibility = View.INVISIBLE
                    retry.visibility = View.VISIBLE
                }
            }
        })
    }

    private fun setUpListeners(){
        TODO("Set up retry button listener")
    }

    private fun fetchData() {
        viewModel.fetchProducts(selectedRadius, latitude, longitude)
        this.setUpObservers()
    }

    private fun prepRequestLocationUpdates() {
        if (ContextCompat.checkSelfPermission(requireActivity().application, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            requestLocationUpdates()
        } else {
            val permissionRequest = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
            requestPermissions(permissionRequest, LOCATION_PERMISSION_REQUEST_CODE)
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        when(requestCode){
            LOCATION_PERMISSION_REQUEST_CODE -> {
                if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    requestLocationUpdates()
                } else {
                    Toast.makeText(requireActivity().application, "Unable to update location without permission", Toast.LENGTH_LONG).show()
                }
            } else -> {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults)
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }

    private fun requestLocationUpdates(){
        viewModel.getLocationData().observe(viewLifecycleOwner, Observer { location ->
            latitude = location.latitude
            longitude = location.longitude
        })
    }

    companion object {
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @return A new instance of fragment Products.
         */
        @JvmStatic
        fun newInstance() =
            ProductsFragment()
    }
}

和適配器

package io.keepcoding.androidfinalproject.ui.products

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import io.keepcoding.androidfinalproject.R
import io.keepcoding.androidfinalproject.domain.Product
import kotlinx.android.synthetic.main.product_item.view.*

class ProductsAdapter(val context: Context, val productClickListener: ((Product) -> Unit)? = null) : RecyclerView.Adapter<ProductsAdapter.ProductHolder>(){

    private var productItems : List<Product> = listOf<Product>()

    private var productsInteractionListener: ((View) -> Unit)? = {
        if(it.tag is Product){
            productClickListener?.invoke(it.tag as Product)
        } else {
            throw IllegalArgumentException("Product item view's tag is not set to a Product object")
        }
    }

    fun setData(productItems: List<Product>){
        this.productItems = productItems
        notifyDataSetChanged()
    }

    inner class ProductHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        var product: Product? = null
            set(value) {
                field = value
                itemView.tag = field
                field?.let {
                    Glide.with(context)
                        .load(it.photos?.get(0))
                        .apply {
                            RequestOptions()
                                .placeholder(R.drawable.ic_launcher_background)
                        }.into(itemView.productImage)
                    itemView.productTitle.text = it.name
                    itemView.productDesc.text = it.description
                    itemView.productPrice.text = (it.price?.toDouble()?.div(100)).toString()
                }
            }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductHolder {
        val view = LayoutInflater.from(context).inflate(R.layout.product_item, parent, false)
        return ProductHolder(view)    }

    override fun getItemCount(): Int {
        return this.productItems.size
    }

    override fun onBindViewHolder(holder: ProductHolder, position: Int) {
        val product = productItems.get(position)
        holder.product = product
        holder.itemView.setOnClickListener(productsInteractionListener)
    }

}

和布局文件

片段布局


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ui.products.ProductsFragment"
     android:layout_height="match_parent"
    android:layout_width="wrap_content"
    >
        <include
            android:id="@+id/loadingView"
            layout="@layout/view_loading"
            />
        <include
            android:id="@+id/retry"
            layout="@layout/view_retry"
            android:visibility="invisible"
            />
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/productsList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="invisible"
            />

</FrameLayout>

項目布局

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="400dp"
    >
    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            >
            <ImageView
                android:id="@+id/productImage"
                android:layout_width="match_parent"
                android:layout_height="250dp"
                />
            <TextView
                android:id="@+id/productTitle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:maxLines="1"
                />
            <TextView
                android:id="@+id/productDesc"
                android:layout_width="match_parent"
                android:layout_height ="wrap_content"
                android:maxLines="4"
                />
            <TextView
                android:id="@+id/productPrice"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:maxLines="1"
                android:layout_gravity="bottom|end"
                />

        </LinearLayout>
    </androidx.cardview.widget.CardView>
</GridLayout>

以及片段布局文件中包含的布局之一

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:gravity="center"
    android:layout_height="wrap_content">

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="@string/loading"
        android:textSize="20sp"
        />
</LinearLayout>

錯過這條線

productsList.adapter = productsAdapter

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM