WIP implementing infinte scroll
This commit is contained in:
parent
eaff3a4965
commit
d470f7e968
@ -46,6 +46,7 @@ dependencies {
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'com.squareup.picasso:picasso:2.8'
|
||||
testImplementation 'junit:junit:4.+'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
@ -11,7 +11,8 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.SubitoBeers">
|
||||
<activity android:name=".MainActivity">
|
||||
<activity android:name=".MainActivity"
|
||||
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
@ -2,19 +2,23 @@ package it.danieleverducci.subitobeers
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.squareup.picasso.Picasso
|
||||
|
||||
import it.danieleverducci.subitobeers.databinding.FragmentBeersListitemBinding
|
||||
import it.danieleverducci.subitobeers.entities.Beer
|
||||
|
||||
class BeerRecyclerAdapter : RecyclerView.Adapter<BeerRecyclerAdapter.ViewHolder>() {
|
||||
|
||||
|
||||
var listener: Listener? = null
|
||||
private val items: ArrayList<Beer> = ArrayList()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
|
||||
return ViewHolder(
|
||||
// Create viewholder
|
||||
val vh = ViewHolder(
|
||||
FragmentBeersListitemBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
@ -22,12 +26,37 @@ class BeerRecyclerAdapter : RecyclerView.Adapter<BeerRecyclerAdapter.ViewHolder>
|
||||
)
|
||||
)
|
||||
|
||||
// Register click listener
|
||||
vh.root.setOnClickListener(object: View.OnClickListener{
|
||||
override fun onClick(v: View?) {
|
||||
if (v != null) {
|
||||
listener?.OnItemClicked(v.getTag() as Beer)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return vh
|
||||
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
|
||||
// Attach item to view to retrieve in case of click
|
||||
holder.root.setTag(item)
|
||||
|
||||
// Fill layout with data
|
||||
holder.name.text = item.name
|
||||
holder.descr.text = item.tagline
|
||||
Picasso.get()
|
||||
.load(item.imageUrl)
|
||||
.placeholder(R.drawable.ic_launcher_foreground)
|
||||
.error(R.drawable.ic_launcher_foreground)
|
||||
.into(holder.pic)
|
||||
|
||||
// If we are drawing the last element, notify
|
||||
if (position == items.size - 1)
|
||||
listener?.OnLastItemScrolled()
|
||||
}
|
||||
|
||||
fun addItems(ni: List<Beer>) {
|
||||
@ -38,8 +67,15 @@ class BeerRecyclerAdapter : RecyclerView.Adapter<BeerRecyclerAdapter.ViewHolder>
|
||||
override fun getItemCount(): Int = items.size
|
||||
|
||||
inner class ViewHolder(binding: FragmentBeersListitemBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
val root: View = binding.root
|
||||
val name: TextView = binding.beerItemName
|
||||
val descr: TextView = binding.beerItemDescr
|
||||
val pic: ImageView = binding.beerItemPic
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun OnItemClicked(item: Beer)
|
||||
fun OnLastItemScrolled()
|
||||
}
|
||||
|
||||
}
|
@ -13,9 +13,11 @@ import it.danieleverducci.subitobeers.entities.Beer
|
||||
/**
|
||||
* A fragment representing a list of Items.
|
||||
*/
|
||||
class BeersFragment : Fragment(), BeersRepository.Listener {
|
||||
class BeersFragment : Fragment(), BeersRepository.Listener, BeerRecyclerAdapter.Listener {
|
||||
|
||||
private val rvAdapter = BeerRecyclerAdapter()
|
||||
private val repo = BeersRepository()
|
||||
private var page = 1
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
@ -30,6 +32,10 @@ class BeersFragment : Fragment(), BeersRepository.Listener {
|
||||
adapter = rvAdapter
|
||||
}
|
||||
}
|
||||
|
||||
// Register for recyclerview adapter events
|
||||
rvAdapter.listener = this
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
@ -37,9 +43,11 @@ class BeersFragment : Fragment(), BeersRepository.Listener {
|
||||
super.onStart()
|
||||
|
||||
// Load beers from network
|
||||
val repo = BeersRepository()
|
||||
repo.listener = this
|
||||
repo.getBeers(1)
|
||||
|
||||
// TODO: evitare che ogni volta ricarichi gli stessi elementi
|
||||
page = 1
|
||||
repo.getBeers(page)
|
||||
}
|
||||
|
||||
override fun onBeersObtained(beers: List<Beer>) {
|
||||
@ -50,4 +58,20 @@ class BeersFragment : Fragment(), BeersRepository.Listener {
|
||||
Toast.makeText(context, R.string.network_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an item is clicked in the list
|
||||
*/
|
||||
override fun OnItemClicked(item: Beer) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when last list item is displayed.
|
||||
* Used to fetch more elements
|
||||
*/
|
||||
override fun OnLastItemScrolled() {
|
||||
page++;
|
||||
repo.getBeers(page)
|
||||
}
|
||||
|
||||
}
|
@ -29,7 +29,7 @@ class BeersRepository {
|
||||
|
||||
override fun onFailure(call: Call<List<Beer>>, t: Throwable) {
|
||||
if (t.message != null)
|
||||
Log.e(TAG, "Unable to obtain beers: ${t.message!!}")
|
||||
Log.e(TAG, "Unable to obtain beers: ${t}")
|
||||
listener?.onFailure()
|
||||
}
|
||||
})
|
||||
|
@ -1,27 +1,21 @@
|
||||
package it.danieleverducci.subitobeers.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
|
||||
class Beer {
|
||||
val id: Int
|
||||
val name: String
|
||||
val tagline: String
|
||||
val description: String
|
||||
val firstBrewed: LocalDate
|
||||
class Beer// Parse date
|
||||
@Throws(JSONException::class) constructor() {
|
||||
val id: Int = 0
|
||||
val name: String = ""
|
||||
val tagline: String = ""
|
||||
val description: String = ""
|
||||
@SerializedName("image_url")
|
||||
val imageUrl: String = ""
|
||||
// @SerializedName("first_brewed")
|
||||
// val firstBrewed: Date? = null
|
||||
|
||||
@Throws(JSONException::class)
|
||||
constructor(jo: JSONObject) {
|
||||
this.id = jo.getInt("id")
|
||||
this.name = jo.getString("name")
|
||||
this.tagline = jo.getString("tagline")
|
||||
this.description = jo.getString("description")
|
||||
|
||||
// Parse date
|
||||
val formatter = DateTimeFormatter.ofPattern("mm/yyyy", Locale.ENGLISH)
|
||||
this.firstBrewed = LocalDate.parse(jo.getString("first_brewed"), formatter)
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package it.danieleverducci.subitobeers.networking
|
||||
|
||||
import com.google.gson.FieldNamingPolicy
|
||||
import com.google.gson.GsonBuilder
|
||||
import it.danieleverducci.subitobeers.Config
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -7,9 +7,8 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/beer_item_pic"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
@ -23,13 +22,15 @@
|
||||
android:id="@+id/beer_item_name"
|
||||
style="@style/Widget.AppCompat.TextView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="19dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:text="Beer name"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/beer_item_descr"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -39,12 +40,12 @@
|
||||
<TextView
|
||||
android:id="@+id/beer_item_descr"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="21dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:maxLines="3"
|
||||
android:text="Beer description lorem ipsum dolor sit amet"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
Loading…
Reference in New Issue
Block a user