Working filter

This commit is contained in:
Daniele 2021-09-05 08:47:14 +02:00
parent 4b4e2b6b3c
commit 91c4485265
13 changed files with 124 additions and 39 deletions

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@ -3,6 +3,7 @@ package it.danieleverducci.subitobeers
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import it.danieleverducci.subitobeers.entities.Beer import it.danieleverducci.subitobeers.entities.Beer
import it.danieleverducci.subitobeers.networking.BeersFilter
import it.danieleverducci.subitobeers.networking.RetrofitProvider import it.danieleverducci.subitobeers.networking.RetrofitProvider
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
@ -16,9 +17,9 @@ class BeersRepository {
var listener: Listener? = null var listener: Listener? = null
fun getBeers(page: Int) { fun getBeers(page: Int, filter: BeersFilter) {
// Obtain beers // Obtain beers
val call = RetrofitProvider.getClient.getBeers(page) val call = RetrofitProvider.getClient.getBeers(page, filter.brewedBefore, filter.brewedAfter)
call.enqueue(object: Callback<List<Beer>> { call.enqueue(object: Callback<List<Beer>> {
override fun onResponse(call: Call<List<Beer>>, response: Response<List<Beer>>) { override fun onResponse(call: Call<List<Beer>>, response: Response<List<Beer>>) {
if (response.body() != null) if (response.body() != null)

View File

@ -15,7 +15,7 @@ class Beer// Parse date
val description: String = "" val description: String = ""
@SerializedName("image_url") @SerializedName("image_url")
val imageUrl: String = "" val imageUrl: String = ""
// @SerializedName("first_brewed") @SerializedName("first_brewed")
// val firstBrewed: Date? = null val firstBrewed: String = ""
} }

View File

@ -0,0 +1,6 @@
package it.danieleverducci.subitobeers.networking
object BeersFilter {
var brewedBefore: String? = null
var brewedAfter: String? = null
}

View File

@ -8,6 +8,8 @@ import retrofit2.http.Query
interface PunkAPI { interface PunkAPI {
@GET("/v2/beers?per_page=10") @GET("/v2/beers?per_page=10")
fun getBeers( fun getBeers(
@Query("page") page: Int @Query("page") page: Int,
@Query("brewed_before") brewedBefore: String?,
@Query("brewed_after") brewedAfter: String?
): Call<List<Beer>> ): Call<List<Beer>>
} }

View File

@ -34,7 +34,7 @@ class BeerDetailFragment(val beer: Beer) : Fragment() {
binding.beerDetailTitle.text = beer.name binding.beerDetailTitle.text = beer.name
binding.beerDetailShortdesc.text = beer.tagline binding.beerDetailShortdesc.text = beer.tagline
binding.beerDetailDesc.text = beer.description binding.beerDetailDesc.text = beer.description
// binding.beerDetailFirstbrewed.text = beer. binding.beerDetailFirstbrewed.text = beer.firstBrewed
return binding.root return binding.root
} }

View File

@ -50,6 +50,7 @@ class BeerRecyclerAdapter : RecyclerView.Adapter<BeerRecyclerAdapter.ViewHolder>
// Fill layout with data // Fill layout with data
holder.name.text = item.name holder.name.text = item.name
holder.descr.text = item.tagline holder.descr.text = item.tagline
holder.firstbrewed.text = item.firstBrewed
Picasso.get() Picasso.get()
.load(item.imageUrl) .load(item.imageUrl)
.placeholder(R.drawable.ic_launcher_foreground) .placeholder(R.drawable.ic_launcher_foreground)
@ -66,8 +67,13 @@ class BeerRecyclerAdapter : RecyclerView.Adapter<BeerRecyclerAdapter.ViewHolder>
} }
fun addItems(ni: List<Beer>) { fun addItems(ni: List<Beer>) {
items.addAll(ni); items.addAll(ni)
notifyDataSetChanged(); notifyDataSetChanged()
}
fun clear() {
items.clear()
notifyDataSetChanged()
} }
override fun getItemCount(): Int = items.size override fun getItemCount(): Int = items.size
@ -76,6 +82,7 @@ class BeerRecyclerAdapter : RecyclerView.Adapter<BeerRecyclerAdapter.ViewHolder>
val root: View = binding.root val root: View = binding.root
val name: TextView = binding.beerItemName val name: TextView = binding.beerItemName
val descr: TextView = binding.beerItemDescr val descr: TextView = binding.beerItemDescr
val firstbrewed: TextView = binding.beerItemFirstbrewed
val pic: ImageView = binding.beerItemPic val pic: ImageView = binding.beerItemPic
val progress: ProgressBar = binding.beerItemProgress val progress: ProgressBar = binding.beerItemProgress
} }

View File

@ -1,5 +1,7 @@
package it.danieleverducci.subitobeers.ui package it.danieleverducci.subitobeers.ui
import android.app.DatePickerDialog
import android.content.res.Resources
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -11,16 +13,21 @@ import it.danieleverducci.subitobeers.BeersRepository
import it.danieleverducci.subitobeers.R import it.danieleverducci.subitobeers.R
import it.danieleverducci.subitobeers.databinding.FragmentBeersListBinding import it.danieleverducci.subitobeers.databinding.FragmentBeersListBinding
import it.danieleverducci.subitobeers.entities.Beer import it.danieleverducci.subitobeers.entities.Beer
import it.danieleverducci.subitobeers.networking.BeersFilter
import java.util.*
/** /**
* A fragment representing a list of Items. * A fragment representing a list of Items.
*/ */
class BeersFragment : Fragment(), BeersRepository.Listener, BeerRecyclerAdapter.Listener { class BeersFragment : Fragment(), BeersRepository.Listener, BeerRecyclerAdapter.Listener {
enum class FILTERTYPE {SINCE, TO}
private val rvAdapter = BeerRecyclerAdapter() private val rvAdapter = BeerRecyclerAdapter()
private val repo = BeersRepository() private val repo = BeersRepository()
lateinit var binding: FragmentBeersListBinding lateinit var binding: FragmentBeersListBinding
private var page = 1 private var page = 1
private var filter = BeersFilter
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
@ -28,12 +35,17 @@ class BeersFragment : Fragment(), BeersRepository.Listener, BeerRecyclerAdapter.
): View? { ): View? {
setHasOptionsMenu(true); setHasOptionsMenu(true);
// Inflate layout
binding = FragmentBeersListBinding.inflate( binding = FragmentBeersListBinding.inflate(
LayoutInflater.from(container!!.context), LayoutInflater.from(container!!.context),
container, container,
false false
) )
// Register filter buttons listeners
binding.listFilterSinceBt.setOnClickListener { onFilterButtonClicked(FILTERTYPE.SINCE) }
binding.listFilterToBt.setOnClickListener { onFilterButtonClicked(FILTERTYPE.TO) }
// Set the adapter // Set the adapter
with(binding.list) { with(binding.list) {
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)
@ -43,18 +55,13 @@ class BeersFragment : Fragment(), BeersRepository.Listener, BeerRecyclerAdapter.
// Register for recyclerview adapter events // Register for recyclerview adapter events
rvAdapter.listener = this rvAdapter.listener = this
return binding.root // Register for network completed events
}
override fun onStart() {
super.onStart()
// Load beers from network
repo.listener = this repo.listener = this
// TODO: evitare che ogni volta ricarichi gli stessi elementi // Load first page
page = 1 loadBeers(true)
repo.getBeers(page)
return binding.root
} }
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@ -86,18 +93,58 @@ class BeersFragment : Fragment(), BeersRepository.Listener, BeerRecyclerAdapter.
throw IllegalStateException("Activity must implement BeerNavigation") throw IllegalStateException("Activity must implement BeerNavigation")
} }
/**
* Called when a filter button is clicked
* @param type whether is start or end date
*/
fun onFilterButtonClicked(type: FILTERTYPE) {
val dpd = DatePickerDialog(requireContext())
// Hide day selector
// dpd.datePicker.findViewById<View>(
// Resources.getSystem().getIdentifier("day", "id", "android")
// ).visibility = View.GONE
dpd.setOnDateSetListener(DatePickerDialog.OnDateSetListener { view, year, month, dayOfMonth ->
// On date chosen
val formattedDate = "${String.format("%02d", month)}-${String.format("%04d", year)}"
if (type == FILTERTYPE.SINCE)
filter.brewedAfter = formattedDate
else
filter.brewedBefore = formattedDate
// Update list
loadBeers(true)
})
dpd.show()
}
/** /**
* Called when last list item is displayed. * Called when last list item is displayed.
* Used to fetch more elements * Used to fetch more elements
*/ */
override fun OnLastItemScrolled() { override fun OnLastItemScrolled() {
page++; page++
repo.getBeers(page) loadBeers(false)
} }
/**
* Toggles beer filter visibility
*/
private fun toggleFilter() { private fun toggleFilter() {
binding.listFilterDropdown.visibility = binding.listFilterDropdown.visibility =
if (binding.listFilterDropdown.visibility == View.VISIBLE) View.GONE else View.VISIBLE if (binding.listFilterDropdown.visibility == View.VISIBLE) View.GONE else View.VISIBLE
} }
/**
* Loads beers from network from first page
* @param clear: clears the list and fetch from first element
*/
private fun loadBeers(clear: Boolean) {
if (clear) {
rvAdapter.clear()
page = 1
}
// Load with filter
repo.getBeers(page, filter)
}
} }

View File

@ -1,11 +0,0 @@
package it.danieleverducci.subitobeers.ui.views
import android.app.DatePickerDialog
import android.content.Context
/**
* Here I extend DatePickerDialog to hide the Day picker
*/
class CustomMonthPickerDialog(context: Context) : DatePickerDialog(context) {
}

View File

@ -0,0 +1,5 @@
<vector android:height="16dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="16dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,3h-1L19,1h-2v2L7,3L7,1L5,1v2L4,3c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,5c0,-1.1 -0.9,-2 -2,-2zM20,21L4,21L4,8h16v13z"/>
</vector>

View File

@ -19,17 +19,19 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginRight="10dp" android:layout_marginEnd="10dp"
android:text="00/0000" android:text="@string/list_filter_brewed_after"
android:drawableLeft="@drawable/ic_firstbrewed"/> app:drawableLeftCompat="@drawable/ic_firstbrewed"
android:drawableTint="@color/white"/>
<Button <Button
android:id="@+id/list_filter_to_bt" android:id="@+id/list_filter_to_bt"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="00/0000" android:text="@string/list_filter_brewed_before"
android:drawableLeft="@drawable/ic_firstbrewed"/> app:drawableLeftCompat="@drawable/ic_firstbrewed"
android:drawableTint="@color/white"/>
</LinearLayout> </LinearLayout>

View File

@ -42,15 +42,30 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_marginBottom="16dp"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="3" android:maxLines="3"
android:text="@string/placeholder_tagline" android:text="@string/placeholder_tagline"
app:layout_constraintBottom_toBottomOf="@+id/beer_item_pic" app:layout_constraintBottom_toTopOf="@+id/beer_item_firstbrewed"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/beer_item_pic" app:layout_constraintStart_toEndOf="@+id/beer_item_pic"
app:layout_constraintTop_toBottomOf="@+id/beer_item_name" /> app:layout_constraintTop_toBottomOf="@+id/beer_item_name" />
<TextView
android:id="@+id/beer_item_firstbrewed"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="16dp"
android:text="@string/placeholder_firstbrewed"
app:drawableLeftCompat="@drawable/ic_firstbrewed_list"
android:drawablePadding="5dp"
android:textStyle="italic"
app:layout_constraintBottom_toBottomOf="@+id/beer_item_pic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/beer_item_pic"
app:layout_constraintTop_toBottomOf="@+id/beer_item_descr" />
<ProgressBar <ProgressBar
android:id="@+id/beer_item_progress" android:id="@+id/beer_item_progress"
android:layout_width="50dp" android:layout_width="50dp"
@ -62,5 +77,4 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/beer_item_pic" /> app:layout_constraintTop_toBottomOf="@+id/beer_item_pic" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -3,6 +3,8 @@
<!-- Beers list --> <!-- Beers list -->
<string name="network_error">Unable to retrieve beers from network</string> <string name="network_error">Unable to retrieve beers from network</string>
<string name="list_filter_brewed_after">Brewed after</string>
<string name="list_filter_brewed_before">Brewed before</string>
<!-- Beers detail --> <!-- Beers detail -->