LoginSignup
10
11

More than 5 years have passed since last update.

PagerTitleStripの制約を回避する

Last updated at Posted at 2014-12-08

はじめに

PagerTabStripはタブ構造を持つUIを作るときにViewPagerとともに使用しますが、
タブ内のFragmentが持つListViewやRecyclerViewのスクロール状況に合わせてToolbar(やActionBar)をPagerTabStripもろとも出したり引っ込めたりする処理を書こうとすると、
PagerTabStripはViewPagerの子要素でなければならないという制約に引っかかってうまく実装できません。

ではどうすればよいのかというと

カスタムビューを作る

  • オリジナルのPagerTabStripをコピーする(クラス名はOverlayPagerTitleStripとする)
  • ソースコードを修正

OverlayPagerTitleStrip.java

public OverlayPagerTitleStrip(Context context, AttributeSet attrs) {
    super(context, attrs);

  /* 中略 */

  /* ここから */
  TypedArray types =
          context.obtainStyledAttributes(attrs, R.styleable.OverlayPagerTitleStrip, 0, 0);
  pagerId = types.getResourceId(R.styleable.OverlayPagerTitleStrip_parentViewPager, 0);
  /* ここまで追加 */
}

@Override protected void onAttachedToWindow() {
  super.onAttachedToWindow();

  final ViewParent parent = getParent();

  ViewPager pager = null;

  if (pagerId != 0) {
    View test2 = ((View) parent).findViewById(pagerId);
    pager = (ViewPager) test2;
  } else if (pagerId == 0 && (parent instanceof ViewPager)) {
    pager = (ViewPager) parent;
  } else if (pagerId == 0 && !(parent instanceof ViewPager)) {
    throw new IllegalStateException(
        "PagerTitleStrip is neither a direct child of a ViewPager nor did you assign the ID of the ViewPager.");
  } else {
    throw new IllegalStateException("PagerTitleStrip: Something went completely wrong.");
  }

  final PagerAdapter adapter = pager.getAdapter();

  pager.setInternalPageChangeListener(mPageListener);
  pager.setOnAdapterChangeListener(mPageListener);
  mPager = pager;
  updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
}
  • カスタムビューの属性を定義する
res/values/attr.xml

<declare-styleable name="OverlayPagerTitleStrip">
  <!-- ViewPagerへの参照 -->
  <attr name="parentViewPager" format="reference" />
</declare-styleable>

使うとき

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <android.support.v4.view.ViewPager
      android:id="@+id/pager"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
  </android.support.v4.view.ViewPager>

  <!-- ViewPagerの子にしなくてもOK -->
  <yourpackage.OverlayPagerTabStrip
      android:id="@+id/strip"
      android:layout_width="match_parent"
      android:layout_height="@dimen/tab_height"
      android:layout_marginTop="?attr/actionBarSize"
      app:parentViewPager="@+id/pager"/>

  <android.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@color/colorPrimary"/>
</FrameLayout>

こんな感じで
手前側 - ToolBar - PagerTabStrip - ViewPager - 奥側
になるようにFrameLayoutで重ねて、タブ内のListViewなどからToolbarと任意のView (ここではPagerTabStrip)を出したり隠したりすればOK
(このへんの処理はGoogle I/O 2014のソースコードを参考)

PagerTabStripはどうすんの?

PagerTitleStripを継承しているので、PagerTabStripのソースコードをコピーすれば多分OK

参考(ほとんどそのまま)

http://stackoverflow.com/questions/14586690/pagertabstrip-position-within-viewpager

おわりに

既に同じことできるライブラリがあったらそれ使ったほうがいいです。
(探してはみたけど見つからなかったので知ってる方がいたら教えて下さい)

10
11
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
10
11