Created
May 1, 2021 09:29
-
-
Save aqua30/b7da69fc8d78c0b117a1fb6dd5bc1d00 to your computer and use it in GitHub Desktop.
Adjusting View Pager which adjusts its height according to the view's height in focus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:fillViewport="true" | |
xmlns:app="http://schemas.android.com/apk/res-auto"> | |
<androidx.constraintlayout.widget.ConstraintLayout | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<com.aqua30.learningproject.AdjustingViewPager | |
android:id="@+id/view_pager" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
app:layout_constraintTop_toTopOf="parent" /> | |
<ImageView | |
android:id="@+id/iv_heart" | |
android:layout_width="@dimen/width_action_icon" | |
android:layout_height="@dimen/height_action_icon" | |
app:layout_constraintStart_toStartOf="parent" | |
android:layout_marginTop="@dimen/margin_16" | |
android:layout_marginStart="@dimen/margin_16" | |
android:src="@drawable/ic_heart" | |
app:layout_constraintTop_toBottomOf="@id/view_pager" /> | |
<ImageView | |
android:id="@+id/iv_comment" | |
android:layout_width="@dimen/width_action_icon" | |
android:layout_height="@dimen/height_action_icon" | |
android:src="@drawable/ic_comment" | |
android:layout_marginStart="@dimen/margin_24" | |
app:layout_constraintStart_toEndOf="@id/iv_heart" | |
app:layout_constraintTop_toTopOf="@id/iv_heart" /> | |
<ImageView | |
android:id="@+id/iv_share" | |
android:layout_width="@dimen/width_action_icon" | |
android:layout_height="@dimen/height_action_icon" | |
android:src="@drawable/ic_share" | |
android:layout_marginStart="@dimen/margin_24" | |
app:layout_constraintStart_toEndOf="@id/iv_comment" | |
app:layout_constraintTop_toTopOf="@id/iv_heart" /> | |
<TextView | |
android:id="@+id/tv_actions_count" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
app:layout_constraintStart_toStartOf="@id/iv_heart" | |
app:layout_constraintTop_toBottomOf="@id/iv_heart" | |
android:layout_marginTop="@dimen/margin_16" | |
android:text="@string/action_count" | |
android:textColor="#95a5a6" | |
android:textSize="@dimen/text_size_12" /> | |
<TextView | |
android:id="@+id/tv_description" | |
android:layout_width="0dp" | |
android:layout_height="0dp" | |
app:layout_constraintStart_toStartOf="@id/iv_heart" | |
app:layout_constraintEnd_toEndOf="parent" | |
app:layout_constraintTop_toBottomOf="@id/tv_actions_count" | |
app:layout_constraintBottom_toBottomOf="parent" | |
android:layout_marginEnd="@dimen/margin_16" | |
android:layout_marginTop="@dimen/margin_16" | |
android:text="@string/description" | |
android:textColor="#000000" | |
android:textSize="@dimen/text_size_16" /> | |
</androidx.constraintlayout.widget.ConstraintLayout> | |
</ScrollView> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.aqua30.learningproject | |
import android.content.Context | |
import android.util.AttributeSet | |
import android.util.Log | |
import android.view.View | |
import android.view.View.MeasureSpec | |
import androidx.viewpager.widget.ViewPager | |
class AdjustingViewPager: ViewPager { | |
private lateinit var currentView: View /* current page view in focus */ | |
private val maxHeight= 480f /* maximum height that we want on screen */ | |
private val allowedHeight = convertDpToPixel(maxHeight) /* allowed height in pixel */ | |
constructor(context: Context) : super(context) | |
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) | |
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { | |
var newViewHeight = heightMeasureSpec | |
val mode = MeasureSpec.getMode(heightMeasureSpec) | |
/* until the parent has not assigned the size to the view | |
and it is either not determined or at its maximum, assign it | |
the new measurement as it comes in focus | |
*/ | |
if (mode == MeasureSpec.UNSPECIFIED || mode == MeasureSpec.AT_MOST) { | |
super.onMeasure(widthMeasureSpec, heightMeasureSpec) | |
if (currentView == null) { | |
super.onMeasure(widthMeasureSpec, heightMeasureSpec) | |
return | |
} | |
try { | |
/* measuring the current dimensions */ | |
currentView.measure( | |
widthMeasureSpec, MeasureSpec.makeMeasureSpec( | |
0, | |
MeasureSpec.UNSPECIFIED | |
) | |
) | |
var currentViewHeight = currentView.measuredHeight | |
/* | |
if the current view height is greater than allowed height then | |
set it to allowed height | |
*/ | |
if (currentViewHeight > allowedHeight) { | |
currentViewHeight = allowedHeight.toInt() | |
} | |
newViewHeight = MeasureSpec.makeMeasureSpec(currentViewHeight, MeasureSpec.EXACTLY) | |
} catch (e: NullPointerException) { | |
Log.e(AdjustingViewPager::class.simpleName, ": " + e.message) | |
} | |
} | |
super.onMeasure(widthMeasureSpec, newViewHeight) | |
} | |
fun measureCurrentView(view: View) { | |
this.currentView = view | |
requestLayout() | |
} | |
private fun convertDpToPixel(dp: Float): Float { | |
val metrics = context.resources.displayMetrics | |
return dp * (metrics.densityDpi / 160f) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.aqua30.learningproject | |
import android.content.Context | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import android.widget.ImageView | |
import androidx.viewpager.widget.PagerAdapter | |
import com.bumptech.glide.Glide | |
class ImagePagerAdapter: PagerAdapter { | |
var imagesList: List<Int>? = null | |
var context: Context? = null | |
var currentPosition = -1 | |
constructor(context: Context, imagesList: List<Int>): super() { | |
this.imagesList = imagesList | |
this.context = context | |
} | |
override fun getCount(): Int { | |
return imagesList?.size!! | |
} | |
override fun isViewFromObject(view: View, `object`: Any): Boolean { | |
return view == `object` | |
} | |
override fun instantiateItem(container: ViewGroup, position: Int): Any { | |
val view = LayoutInflater.from(context).inflate(R.layout.view_item, container, false) | |
val imageView: ImageView = view.findViewById(R.id.iv_item) | |
container.addView(view) | |
Glide.with(context!!) | |
.load(imagesList?.get(position)) | |
.into(imageView) | |
return view | |
} | |
override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) { | |
super.setPrimaryItem(container, position, `object`) | |
if (container !is AdjustingViewPager) | |
return | |
if (position != currentPosition) { | |
val viewPager: AdjustingViewPager = container | |
currentPosition = position; | |
viewPager.measureCurrentView(`object` as View) | |
} | |
} | |
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { | |
container.removeView(`object` as View) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.aqua30.learningproject | |
import android.os.Bundle | |
import androidx.appcompat.app.AppCompatActivity | |
class MainActivity : AppCompatActivity() { | |
lateinit var viewPager : AdjustingViewPager | |
lateinit var imageAdapter: ImagePagerAdapter | |
private val imagesList: List<Int> = listOf( | |
R.drawable.img_1, | |
R.drawable.img_2, | |
R.drawable.img_3 | |
) | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(R.layout.activity_main) | |
viewPager = findViewById(R.id.view_pager) | |
imageAdapter = ImagePagerAdapter(this, imagesList) | |
viewPager.adapter = imageAdapter | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:maxHeight="430dp"> | |
<ImageView | |
android:id="@+id/iv_item" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content"/> | |
</FrameLayout> |
Ah OK sorry, I misunderstood the whole thing then. Let me clarify my points though.
1 - your property is a lateinit var and has a type of View, i.e. it can never be null. This means that the null check at AdjustingViewPager:28 can never return true
3 - It's just a convenience thing. You can declare the whole class as
class ImagePagerAdapter(private val context: Context, private val imagesList: List<Int>)
and get rid of an extra constructor and the first two vars
Agreed @kryanod. Will update this.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@kryanod This is not auto-migrated code from java. I wrote it in kotlin.
Let me know what issues you're facing.
For the point 1, are you calling
viewPager.measureCurrentView(
objectas View)
because otherwise you'll getcurrentView cannot be null
For point 2, as I'm learning kotlin so i used the defaults.
For point 3, please provide exact error you get.