0
0

More than 1 year has passed since last update.

【Android】高さがwrap_contentのViewPager2を作成

Last updated at Posted at 2023-08-24

はじめに

高さがwrap_contentのViewPager2を作成する方法について解説。
例えば、ScrollView内にViewPager2を入れて高さをmatch_parentにできないことがある。
高さが決まっている場合は数値で指定すればいいが、ページ毎にビューの高さが変わっても対応できるプログラムを作成。

コード

例として、ScrollView内にViewPager2を入れたコードを作ってみる。

ポイントは、ViewPagerのページ切り替え時(onPageSelected)、binding.viewPager.layoutParamsによりViewPagerの高さを動的に変更している。

レイアウト

ViewPager内に入れるレイアウト。動画の青と緑のビュー部分。

view_pager.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<TextView
		android:id="@+id/view"
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:gravity="center"
		android:textColor="@color/white"
		android:textSize="28sp"/>
</androidx.constraintlayout.widget.ConstraintLayout>

メインレイアウト。ScrollView内の上部に動画の赤のビュー部分、下部にViewPagerを配置。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
	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">

	<androidx.constraintlayout.widget.ConstraintLayout
		android:layout_width="match_parent"
		android:layout_height="wrap_content">

		<TextView
			android:id="@+id/view1"
			android:layout_width="0dp"
			android:layout_height="600dp"
			android:background="#FF6363"
			android:gravity="center"
			android:text="Height : 600dp"
			android:textColor="@color/white"
			android:textSize="28sp"
			app:layout_constraintEnd_toEndOf="parent"
			app:layout_constraintStart_toStartOf="parent"
			app:layout_constraintTop_toTopOf="parent"/>

		<androidx.viewpager2.widget.ViewPager2
			android:id="@+id/view_pager"
			android:layout_width="0dp"
			android:layout_height="wrap_content"
			app:layout_constraintEnd_toEndOf="parent"
			app:layout_constraintStart_toStartOf="parent"
			app:layout_constraintTop_toBottomOf="@id/view1"/>
	</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

内部処理

Adapterの作成。ここではholder.binding.view.layoutParams.heightでプログラムでの高さ変更を行なっている。

ViewPagerAdapter.kt
class ViewPagerAdapter : RecyclerView.Adapter<ViewPagerAdapter.ViewHolder>() {
	inner class ViewHolder(val binding: ViewPagerBinding) : RecyclerView.ViewHolder(binding.root)

	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(ViewPagerBinding.inflate(LayoutInflater.from(parent.context), parent, false))
	override fun getItemCount() = 2
	override fun onBindViewHolder(holder: ViewHolder, position: Int) {
		val height = 300 * (position + 1)
		holder.binding.view.text = "Height: ${height}dp"
		holder.binding.view.setBackgroundColor(Color.parseColor(if (position == 0) "#6200EE" else "#03DAC6"))

		val density = holder.binding.root.context.resources.displayMetrics.density
		holder.binding.view.layoutParams.height = (height * density).toInt()
	}
}

最後に、メインレイアウト内の処理。onPageSelectedメソッド内でbinding.viewPager.layoutParamsの値を変更してViewPager2の高さを変更しているのがポイント。
また、findViewByPositionの戻り値がnullにならないように、doOnPreDraw内で処理を行う。

MainActivity.kt
class MainActivity : AppCompatActivity() {
	private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		setContentView(binding.root)

		binding.viewPager.adapter = ViewPagerAdapter()
		binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
			override fun onPageSelected(position: Int) {
				binding.viewPager.doOnPreDraw {
					val view = (binding.viewPager[0] as RecyclerView).layoutManager?.findViewByPosition(position)
					view?.post {
						val wMeasureSpec = MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY)
						val hMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
						view.measure(wMeasureSpec, hMeasureSpec)

						if (binding.viewPager.layoutParams.height != view.measuredHeight) {
							binding.viewPager.layoutParams = binding.viewPager.layoutParams.apply { height = view.measuredHeight }
						}
					}
				}
			}
		})
	}
}

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0