Xamarin.AndroidでViewPagerをlayout_height="wrap_content"にする(高さを変更する)

AndroidのViewPagerはlayout_height="wrap_content"

を設定してもデフォルトでは画面一杯にViewPagerが表示されてしまいます。

下記のリンクでこの問題に対する解決策は提案されていますが、

stackoverflow.com

 

Xamarin.Androidではどうしたら良いのかというのを、

Xamarinの公式ホームページにあるサンプルを元に実装していきたいと思います。

TreePager - Xamarin

 

まずは、ViewPagerの下に表示する項目を追加します。

上から順にViewPager , 画像の説明文という並びにしたいので、

ViewPagerをLinearLayoutの子要素にします。

さらにそのLinearLayoutにLinearLayoutを追加し、

子要素としてTextViewを加えます。

ついでに、ここでViewPagerをlayout_height="wrap_content"にしてみます。


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textAlignment="center">

	<android.support.v4.view.ViewPager
    	android:id="@+id/viewpager"
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content">
    <android.support.v4.view.PagerTabStrip
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:textColor="#fff" />
	</android.support.v4.view.ViewPager>
	
	<LinearLayout
        android:orientation="vertical"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/linearLayout2">
        <TextView
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textView1"
            android:gravity="center"
            android:text="画像1の説明です"
            android:layout_marginTop="78.0dp"
            android:layout_marginBottom="61.5dp"
            android:textColor="@android:color/white"/>
    </LinearLayout>
	
</LinearLayout>

この状態で一度起動してみます。

 

f:id:dev_suesan:20170307015456p:plain

 

やはりこれでは下のTextViewは表示されないようです。

それではリンクにあるやり方を参考にして、ViewPagerを継承したサブクラスを作っていこうと思います。

今回はこのサブクラスをMyPagerとします。

MyPagerではViewPagerのOnMeasureメソッドを拡張します


using Android.Views;
using Android.Widget;

namespace TreePager
{
	public class MyPager : ViewPager
	{
		//両コンストラクタも必要になるため記述します。
		public MyPager(Context subContext) : base(context: subContext)
		{
		}

		public MyPager(Context subContext, IAttributeSet subIAttributeSet) : base(context: subContext, attrs: subIAttributeSet)
		{
		}

		//このメソッドでViewPagerの高さが決まります。
		protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
		{
			//このメソッドが呼ばれるタイミングとしては、初期表示時と画像切り替わり時のようです。
			//childに設定されるのは前後のImageViewとPagerTabStripで、このサンプルの場合は、
			//1枚目の画像がやたらと大きいので1枚目と2枚目の表示がうまくいきません。
			int height = 0;
			for (int i = 0; i < this.ChildCount; i++)
			{
				View child = this.GetChildAt(i);
				if (!(child is ImageView)) continue;
				child.Measure(widthMeasureSpec, MeasureSpec.MakeMeasureSpec(0, MeasureSpecMode.Unspecified));
				int h = child.MeasuredHeight;
				if (h > height) height = h;
			}

			heightMeasureSpec = MeasureSpec.MakeMeasureSpec(height, MeasureSpecMode.Exactly);

			//ここで固定の高さを渡してあげる方法だと安定するかもです
			//heightMeasureSpec = MeasureSpec.MakeMeasureSpec(800, MeasureSpecMode.Exactly);

			base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
		}
	}
}

次にレイアウトに設定されているViewPagerをMyPagerに置き換えます

※継承した要素を指定する場合はnamespace名(小文字).クラス名で指定します。


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textAlignment="center">

	<treepager.MyPager
    	android:id="@+id/viewpager"
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content">
    <android.support.v4.view.PagerTabStrip
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:textColor="#fff" />
	</treepager.MyPager>
	
	<LinearLayout
        android:orientation="vertical"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/linearLayout2">
        <TextView
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textView1"
            android:gravity="center"
            android:text="画像1の説明です"
            android:layout_marginTop="78.0dp"
            android:layout_marginBottom="61.5dp"
            android:textColor="@android:color/white"/>
    </LinearLayout>
	
</LinearLayout>

これで実行してみると下の画像のようになります。

※固定の高さで設定しています。

 

f:id:dev_suesan:20170307015522p:plain

 

 

上手く表示されました!!

 

MyPagerのコード中にも記載しましたが、

サンプルの用に子の要素の高さだけで判断すると上手くいかないケースがあります

(もちろんリンク先の投稿者も一例として示したのだと思います)。

 

実際に使用する場合は、環境に合わせて値を算出して設定する必要があります。