Android studio 3.6
In my activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dataBinding =
DataBindingUtil.setContentView<SelectionActivityBinding>(
this,
R.layout.selection_activity
)
dataBinding.setHandler(this)
setSupportActionBar(dataBinding.toolBarContainer.toolBar)
getSupportActionBar()!!.setDisplayHomeAsUpEnabled(true)
getSupportActionBar()!!.setDisplayShowTitleEnabled(false)
val articlesList = mutableListOf<Article>()
val article1 = Article()
article1.title = "111111"
articlesList.add(article1)
val article2 = Article()
article1.title = "222222"
articlesList.add(article2)
articleAdapter = ArticleAdapter()
articleAdapter.setList(articlesList)
dataBinding.viewPager2.adapter = articleAdapter
}
Here xml layout:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="handler"
type="com.myproject.ui.activity.SelectionActivity" />
</data>
<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="300dp"
android:background="#bbccaa"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolBarContainer" />
here custom adapter:
class ArticleAdapter : RecyclerView.Adapter<ArticleAdapter.ArticleViewHolder>() {
var articleList: List<Article> = mutableListOf()
companion object {
private val TAG = ArticleAdapter::class.java.name
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
return ArticleViewHolder(parent)
}
override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
Debug.d(TAG, "onBindViewHolder: position = $position")
holder.bind(articleList[position])
}
fun setList(articleList: List<Article>) {
this.articleList = articleList
notifyDataSetChanged()
}
override fun getItemCount(): Int = articleList.size
class ArticleViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
constructor(parent: ViewGroup) :
this(
LayoutInflater.from(parent.context).inflate(
R.layout.article_item,
parent,
false
)
)
fun bind(article: Article) {
Debug.d(TAG, "bind: article = $article")
itemView.titleTextView.text = article.title
}
}
}
But as result it show empty viewpager2 (green background). No inner item in viewPager2. As result no swiping.
Related
[enter image description here][1]
[enter image description here][2]VHFV.png
strong text
[2]: https://i.stack.imgur.com/YJOpm.png
activity_main
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#170628"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_images"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
image_layout.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:layout_width="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_margin="5dp"
app:cardCornerRadius="10dp"
android:layout_height="100dp">
<ImageView
android:id="#+id/big_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/zone_images" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var zoneBinding: ActivityMainBinding
var image = ArrayList<String>()
lateinit var zoneAdapter:ZoneImagesAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
zoneBinding= DataBindingUtil.setContentView(this,R.layout.activity_main)
buildData()
setRecyclerView()
}
private fun buildData() {
image.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQzx__blVU5FWJAUCU4d9-E095_n3Fgy1tuxA&usqp=CAU")
image.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQh90iDDn5BoUnZqANXUszd17_Q-RhfRo8V6Q&usqp=CAU")
image.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQzx__blVU5FWJAUCU4d9-E095_n3Fgy1tuxA&usqp=CAU")
image.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQh90iDDn5BoUnZqANXUszd17_Q-RhfRo8V6Q&usqp=CAU")
image.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQzx__blVU5FWJAUCU4d9-E095_n3Fgy1tuxA&usqp=CAU")
image.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQh90iDDn5BoUnZqANXUszd17_Q-RhfRo8V6Q&usqp=CAU")
}
private fun setRecyclerView() {
zoneAdapter = ZoneImagesAdapter(image)
val flexboxLayoutManager = FlexboxLayoutManager(this)
flexboxLayoutManager.flexDirection =FlexDirection.ROW
flexboxLayoutManager.flexWrap = FlexWrap.WRAP
flexboxLayoutManager.justifyContent = JustifyContent.CENTER
flexboxLayoutManager.alignItems = AlignItems.STRETCH
zoneBinding.rvImages.apply {
adapter=zoneAdapter
layoutManager=flexboxLayoutManager
}
}
Adapter
class ZoneImagesAdapter (var listOfImageUrl:ArrayList<String>):
RecyclerView.Adapter<ZoneImagesAdapter.ImageViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.big_image_layout, parent, false)
return ImageViewHolder(view)
}
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
val image = listOfImageUrl[position]
holder.setImages(image)
}
override fun getItemCount(): Int {
return listOfImageUrl.size
}
class ImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var zoneImage:ImageView=itemView.findViewById(R.id.big_image)
fun setImages(images: String) {
Glide.with(zoneImage).load(images).into(zoneImage)
val layoutParams:ViewGroup.LayoutParams = zoneImage.layoutParams
if (layoutParams is FlexboxLayoutManager.LayoutParams){
val flexboxLp:FlexboxLayoutManager.LayoutParams= layoutParams as FlexboxLayoutManager.LayoutParams
flexboxLp.flexGrow= 1.0f
}
}
}
}
How can I achieve this layout that is showing inside image using recyclerView, ?? I use flexboxLayoutManager for this but I do not know how can I used, Can anyone help me to make this layout that is showing inside image
I'm trying to create a nested recycler view with data received from the server(using Retrofit). The outer recyclerview prints fine, but the inner recyclerview doesn't print at all.
No Error, No Warning...I don't know why. please Help.
my recylcerview blueprint here
Layout Code
the layout xml look like this
(1) activity_main
<androidx.coordinatorlayout.widget.CoordinatorLayout
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=".MainActivity">
<com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.CollapsingToolbarLayout ...>
<androidx.appcompat.widget.Toolbar
android:id="#+id/homeToolbar" ... />
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="#+id/homeLogo" ... />
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/homeBanner" ... />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/outerRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="50dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="50dp" ... />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
(2) item_outer_recycler
<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="wrap_content">
<ImageView
android:id="#+id/houseImage"
android:contentDescription="main image"
android:layout_width="match_parent"
android:layout_height="150dp".../>
<TextView
android:id="#+id/houseName"
android:layout_width="200dp"
android:layout_height="30dp"
tools:text="some name" ... />
<TextView
android:id="#+id/houseAddress"
android:layout_width="300dp"
android:layout_height="20dp"
android:layout_marginStart="15dp"
tools:text="some address" ... />
<TextView
android:id="#+id/houseHomepage"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="15dp".../>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/innerRecycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(3) item_inner_recycler
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tool="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="#+id/houseTag"
android:layout_width="50dp"
android:layout_height="20dp"
android:textSize="12sp"
android:textColor="#878d95"
android:background="#e4e7ed"
android:textAlignment="center"
tool:text="roop top"/>
</LinearLayout>
Adapters Code
(1) outer recycler adapter
class MainHouseHolder(val binding: ItemOuterRecyclerBinding): RecyclerView.ViewHolder(binding.root)
class MainHouseAdapter(private val context: Context, private val data: List<House>):
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun getItemCount(): Int = data.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainHouseHolder =
MainHouseHolder(ItemOuterRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val house = data[position]
val binding = (holder as MainHouseHolder).binding
binding.innerRecycler.adapter = MainTagAdapter(house.tags)
binding.innerRecycler.layoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
// process outer recycler view
}
}
(2) inner recycler adapter
class MainTagHolder(val binding: ItemInnerRecyclerBinding) : RecyclerView.ViewHolder(binding.root)
class MainTagAdapter(private val data: String) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var tagData :MutableList<String> = mutableListOf()
override fun getItemCount(): Int {
tagData = data.split(",") as MutableList<String>
return tagData.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainTagHolder =
MainTagHolder(ItemInnerRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val binding = (holder as MainTagHolder).binding
binding.houseTag.text = tagData[position]
}
}
Activity Code
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var houseList : List<House>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.homeToolbar)
val apiClient = APIClient().connectInterface
val houseCall = apiClient.getHouseList()
houseCall.enqueue(object : Callback<HouseList> {
override fun onResponse(call: Call<HouseList>, response: Response<HouseList>) {
Log.d("CONNECTOR", "ON_RESPONSE")
houseList = response.body()?.list as List<House>
val adapter = MainHouseAdapter(applicationContext, houseList)
binding.houseList.adapter = adapter
binding.houseList.layoutManager = LinearLayoutManager(applicationContext)
adapter.notifyDataSetChanged()
}
override fun onFailure(call: Call<HouseList>, t: Throwable) {
Log.d("CONNECTOR", "FAILURE")
t.printStackTrace()
}
})
}
}
in item_outer_recycler
change
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/innerRecycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="parent" />
to
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/innerRecycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/houseAddress" />
I think you should change outer adapter from
class MainHouseHolder(val binding: ItemOuterRecyclerBinding): RecyclerView.ViewHolder(binding.root)
class MainHouseAdapter(private val context: Context, private val data: List<House>):
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun getItemCount(): Int = data.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainHouseHolder =
MainHouseHolder(ItemOuterRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val house = data[position]
val binding = (holder as MainHouseHolder).binding
binding.innerRecycler.adapter = MainTagAdapter(house.tags)
binding.innerRecycler.layoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
// process outer recycler view
}
}
to
class MainHouseAdapter(private val context: Context, private val data: List<House>):
RecyclerView.Adapter<MainHouseAdapter.MainHouseHolder>() {
override fun getItemCount(): Int = data.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainHouseHolder =
MainHouseHolder(ItemOuterRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val house = data[position]
val binding = (holder as MainHouseHolder).binding
binding.innerRecycler.adapter = MainTagAdapter(house.tags)
binding.innerRecycler.layoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
// process outer recycler view
}
inner class MainHouseHolder(val binding: ItemOuterRecyclerBinding): RecyclerView.ViewHolder(binding.root)
}
and make inner adapter like outer too
class MainTagAdapter(private val data: String) : RecyclerView.Adapter<MainTagAdapter.MainTagHolder>() {
var tagData :MutableList<String> = mutableListOf()
override fun getItemCount(): Int {
tagData = data.split(",") as MutableList<String>
return tagData.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainTagHolder =
MainTagHolder(ItemInnerRecyclerBinding.inflate(LayoutInflater.from(parent.context), parent, false))
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val binding = (holder as MainTagHolder).binding
binding.houseTag.text = tagData[position]
}
inner class MainTagHolder(val binding: ItemInnerRecyclerBinding) : RecyclerView.ViewHolder(binding.root)
}
Oh...the problem was that innerRecycler was set to app:layout_constraintTop_toBottomOf="parent" . I made a stupid mistake.
I'm sorry
I want to bind data to my recylerview adapter. This is my current code following the MVVM pattern
Fragment
class NotificationFragment : Fragment() {
var customeProgressDialog: CustomeProgressDialog? = null
private val appPreferences: AppPreference by inject()
private val notificationViewModel: NotificationViewModel by viewModel()
private lateinit var binding: FragmentNotificationBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentNotificationBinding.inflate(inflater, container, false)
return binding.getRoot()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.notification.layoutManager=LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
customeProgressDialog = CustomeProgressDialog(activity)
notificationViewModel.notifications(
appPreferences.getUsername(),
appPreferences.getPassword(),
appPreferences.getUserId()
)
initObservables()
}
private fun initObservables() {
notificationViewModel.progressDialog?.observe(this, Observer {
if (it!!) customeProgressDialog?.show() else customeProgressDialog?.dismiss()
})
notificationViewModel.apiResponse?.observe(
viewLifecycleOwner,
androidx.lifecycle.Observer { response ->
if (response.dataList != null) {
val notificationAdapter = NotificationAdapter(response.dataList as List<Data>)
notificationAdapter.notifyDataSetChanged()
binding.notification.adapter = notificationAdapter
}
})
}
}
View model
class NotificationViewModel(networkCall: NetworkCall) : ViewModel(),
Callback<ApiResponse> {
var progressDialog: SingleLiveEvent<Boolean>? = null
var apiResponse: MutableLiveData<ApiResponse>? = null
var networkCall: NetworkCall;
init {
progressDialog = SingleLiveEvent<Boolean>()
apiResponse = MutableLiveData<ApiResponse>()
this.networkCall = networkCall
}
fun notifications(username: String?, password: String?, userId: String?) {
progressDialog?.value = true
val apiPost = ApiPost()
apiPost.userName = username
apiPost.password = password
apiPost.UserId = userId
apiPost.FileType = NetworkConstant.FILE_TYPE_NOT
networkCall.getPDF(apiPost).enqueue(this)
}
override fun onFailure(call: Call<ApiResponse>, t: Throwable) {
progressDialog?.value = false
}
override fun onResponse(call: Call<ApiResponse>, response: Response<ApiResponse>) {
progressDialog?.value = false
apiResponse?.value = response.body()
}
}
The adapter
class NotificationAdapter(private val list: List<Data>) :
RecyclerView.Adapter<NotificationAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ElementListBinding.inflate(inflater)
// val view = inflater.inflate(R.layout.element_list, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val movie: Data = list[position]
holder.bind(movie)
holder.itemView.setOnClickListener {
if (!TextUtils.isEmpty(movie.filePath)) {
try {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(movie.filePath))
holder.itemView.context.startActivity(browserIntent)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
override fun getItemCount(): Int = list.size
inner class ViewHolder(binding: ElementListBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(movie: Data) {
binding.item = movie
}
}
}
unable to find binding object
the recylerview element list xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="data"
type="com.mountmeru.model.Data" />
</data>
<androidx.cardview.widget.CardView
android:id="#+id/main_cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/main_cardrl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<RelativeLayout
android:id="#+id/rl_newsdate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.3">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tv_notifi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:maxLines="2"
android:text="#{data.displayName}"
android:textColor="#android:color/black"
android:textSize="16sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tv_brief"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/tv_notifi"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginRight="10dp"
android:textColor="#android:color/black"
android:textSize="16sp"
android:visibility="gone" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/tv_brief"
android:layout_marginLeft="10dp"
android:layout_marginTop="2dp"
android:layout_marginRight="10dp"
android:maxLines="1"
android:text="hey i am date"
android:textColor="#color/inactive_text"
android:textSize="14sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#+id/rl_newsdate"
android:layout_weight="0.7"
android:padding="5dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/iv_notifi"
android:layout_width="match_parent"
android:layout_height="75dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="#drawable/mer" />
</RelativeLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.cardview.widget.CardView>
</layout>
Can someone confirm me is my implementation of MVVM correct or it needs some refactoring?
How do I make of data binding in my recyclerview list element xml?
You have already used <layout> as parent tag in element_list.xml. Now you can inflate it in the adapter class using DataBinding. See the example below:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ElementListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(Binding)
}
You have to modify your ViewHolder class as well as shown below:
inner class ViewHolder(val binding: ElementListBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(movie: Data) {
with(itemView) {
binding.tvNotifi.text = movie.displayName
binding.tvDate.text = movie.UpdatedDate
if (movie.description != null) {
binding.tvBrief.text = movie.description
binding.tvBrief.visibility = View.VISIBLE
}
}
}
}
I am developing news app using kotlin but it is showing empty white screen and there is no error or exception on the logcat
below my SportNewsAdapter.kt
class SportNewsAdapter(val context: Context) : RecyclerView.Adapter<SportNewsAdapter.MyViewHolder>() {
var articleList : List<Article> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.news_list,parent,false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return articleList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.tvMovieName.text = articleList.get(position).title
Glide.with(context).load(articleList.get(position).urlToImage)
.apply(RequestOptions().centerCrop())
.into(holder.image)
}
fun setMovieListItems(movieList: List<Article>){
this.articleList = articleList;
notifyDataSetChanged()
}
class MyViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!) {
val tvMovieName: TextView = itemView!!.findViewById(R.id.title)
val image: ImageView = itemView!!.findViewById(R.id.image)
}
}
below news_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="150dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#android:color/white"
android:textStyle="bold"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
below MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var recyclerView: RecyclerView
lateinit var sportNewsAdapter: SportNewsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView = findViewById(R.id.recyclerView)
sportNewsAdapter = SportNewsAdapter(this)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = sportNewsAdapter
val apiInterface = SportNewsInterface.create().getNews()
apiInterface.enqueue( object : Callback<List<Article>> {
override fun onResponse(call: Call<List<Article>>?, response: Response<List<Article>>?) {
if(response?.body() != null)
sportNewsAdapter.setMovieListItems(response.body()!!)
}
override fun onFailure(call: Call<List<Article>>?, t: Throwable?) {
}
})
}
}
below activity_main.xml
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
below SportNewsInterface.kt
interface SportNewsInterface {
#GET("v2/top-headlines?country=us&apiKey=da331087e3f3462bb534b3b0917cbee9")
fun getNews() : Call <List<Article>>
companion object {
var BASE_URL = "https://newsapi.org/"
fun create() : SportNewsInterface {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
return retrofit.create(SportNewsInterface::class.java)
}
} }
below SportNewsResponse.kt where implemented retrofit
data class SportNewsResponse(
val articles: List<Article>,
val status: String,
val totalResults: Int
)
Change recycler view height to wrap content and run again
I'm unable to update my RecyclerView. Tried every solution on stackoverflow but nothing helps. I've tried to add layoutmanager in code, hardcode number of items, made new files, checked if I had duplicate files etc.. I also debugged and confirmed that "onAttachedToRecyclerView" is called, but getItemCount and the others i've listed in the adapter are not called except for the constructor
Adapter:
class BaseAdapter(context: Context, val items: List<Item>) :
RecyclerView.Adapter<LineBoxAdapter.BaseAdapter>() {
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.text = items[position].text
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
ViewHolder {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.simple_item,
parent,
false
)
)
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textView = itemView.findViewById<TextView>(R.id.title)
}
}
Function that updates recyclerView:
val listView =
LayoutInflater.from(context).inflate(R.layout.list, viewGroup,
false)
val list = listView.findViewById<RecyclerView>(R.id.
LinearLayoutManager(context)
val adapter = BaseAdapter(context, items)
list.adapter = adapter
adapter.notifyDataSetChanged()
RECYCLERVIEW:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/items_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:overScrollMode="never"
android:requiresFadingEdge="horizontal"
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
SIMPLE_ITEM:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:orientation="horizontal">
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="25" />
</LinearLayout>
You should avoid using existing class names from API.
I will post my working code.
simple_item:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text_simple_item"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
RecyclerAdapter:
class RecyclerAdapter(context: Context, val items: List<Item>) :
RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>() {
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = items[position].itemName
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
MyViewHolder {
return MyViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.simple_item,
parent,
false
)
)
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textView = itemView.findViewById<TextView>(R.id.text_simple_item)
}
}
My Activity:
class RecyclerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recycler)
val recyler = findViewById<RecyclerView>(R.id.rv_activity_recycler)
val list = mutableListOf(Item("Me"), Item("You"), Item("We"))
val adapter = RecyclerAdapter(this, list)
recyler.layoutManager = LinearLayoutManager(this)
recyler.adapter = adapter
}
}
My Item:
class Item(val itemName: String)