Thursday, 28 October 2021

How to create a dynamic height wrapping ViewPager when content have variable heights on Android.

  No comments

import android.content.Context
import android.util.AttributeSet
import androidx.viewpager.widget.ViewPager
class DynamicHeightViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : ViewPager(context, attrs) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var heightMeasureSpec = heightMeasureSpec
var height = 0
for (i in 0 until childCount) {
val child = getChildAt(i)
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
val h = child.measuredHeight
if (h > height) height = h
}
if (height != 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}}
private fun renderRegionalOfferList(offers: List<Offer>?) {
val offerAdapter = RegionalOffersAdapter(requireContext(), localViewModel.offerClickSubject, offers)
binding.viewRegionalOffers.viewPager.adapter = offerAdapter
binding.viewRegionalOffers.viewPager.offscreenPageLimit = 2
binding.viewRegionalOffers.viewPager.pageMargin=18
dotscount = offerAdapter.count
dots = arrayOfNulls(dotscount)
//adding dots base don dotscount ie. total number of images
for (i in 0 until dotscount) {
dots[i] = ImageView(requireContext())
dots[i]!!.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.non_active_dot))
val param = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
param.setMargins(8, 0, 8, 0)
binding.viewRegionalOffers.sliderDots.addView(dots[i], param)
}
//0 position active by default
dots[0]!!.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.active_dot))
//image slider listener
binding.viewRegionalOffers.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageSelected(position: Int) {
for (i in 0 until dotscount) {
dots[i]!!.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.non_active_dot))
}
dots[position]!!.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.active_dot))
}
override fun onPageScrollStateChanged(state: Int) {
}
})
//offerAdapter.swapData(offers)
}
view raw MainActivity.kt hosted with ❤ by GitHub
class RegionalOffersAdapter(
private val context: Context,
private val clickSubject: PublishSubject<Offer>,
val items: List<Offer>?
) : PagerAdapter() {
//private val items = mutableListOf<Offer>()
override fun getCount(): Int = items?.size ?: 0
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val view = inflater.inflate(R.layout.item_regional_offer, null)
val image = view.findViewById<ImageView>(R.id.image)
val offerTitle = view.findViewById<TextView>(R.id.offer_title)
val name = view.findViewById<TextView>(R.id.name)
val ratingFollowers = view.findViewById<TextView>(R.id.rating_followers)
val amount = view.findViewById<TextView>(R.id.amount)
val categoryLocationContainer = view.findViewById<FancyCategoryLocationChipView>(R.id.category_location_container)
name.text = items?.get(position)?.createdByCompany?.user?.name ?: "Company"
offerTitle.text = items?.get(position)?.name ?: "Test offer"
image.setImageBitmap(
BitmapFactory.decodeResource(
view.context.resources,
R.drawable.profile_placeholder
)
)
amount.text = "${items?.get(position)?.rewards?.get(0)?.unit ?: "$"} ${items?.get(position)?.rewards?.get(0)?.amount ?: "0"}"
view.setOnClickListener {
InfluencerOfferDetailsActivity.start(context, items?.get(position)?.id ?: 0)
}
items?.get(position)?.mainImage?.let {
Picasso.get().load(it.getImagePath())
.placeholder(R.drawable.profile_placeholder)
.error(R.drawable.profile_placeholder)
.into(image)
}
//offerContainer.setOnClickListener { clickSubject.onNext(offerModel) }
ratingFollowers.text = "Rating: ${items?.get(position)?.createdByCompany?.user?.calculatedRating ?: 0} | ${items?.get(position)?.minimumAudienceCount} Min Followers"
categoryLocationContainer.setupView3(context, items?.get(position)?.categories, items?.get(position)?.audienceLocations)
//categoryLocationContainer.setupView(context)
val vp = container as ViewPager
vp.addView(view, 0)
return view
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view === `object`
}
fun swapData(items: List<Offer>?) {
/* this.items.clear()
if (!items.isNullOrEmpty()) {
this.items.addAll(items.sortedWith(compareBy { it.status?.shortName }))
}
notifyDataSetChanged()*/
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
val vp = container as ViewPager
val view = `object` as View
vp.removeView(view)
}
override fun getPageWidth(position: Int): Float {
return .8f
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:id="@+id/regionalOfferContainer"
android:backgroundTint="@color/white"
android:background="@drawable/top_rounded_background"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView9"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="22dp"
android:layout_marginEnd="16dp"
android:fontFamily="@font/montserrat_semi_bold"
android:text="@string/label_regional_offers"
android:textColor="@color/fancy_black_60"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.sway.android.utils.view.DynamicHeightViewPager
android:id="@+id/viewPager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="18dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView9">
</com.sway.android.utils.view.DynamicHeightViewPager>
<LinearLayout
android:id="@+id/sliderDots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/viewPager" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

No comments :

Post a Comment