ひらい ぶらり Hi-Library

ぷろぐらみんぐについて。ときどきどうでもいいことについて。

ListViewの中にViewPagerを入れる場合の注意

今回ListViewのheaderに、横にスワイプしたりフリックしたりすることで画像が切り替わる様なビューを入れることになったのですが、困ったことになりました。

ここまで読んでピンと来て解決策だけ知りたい方はすっ飛ばして下の方を読んでくだい。

で、どんなことが起きたのかと言いますと。

f:id:shin_bashi:20130529184624p:plain

青い部分がListView、で、そのHeaderの中に入っているViewPagerが緑の部分です。 ViewPagerの部分は横フリックしたら動く、縦にフリックすればListViewが動く。という期待をしていたのですが、少し違いました。

f:id:shin_bashi:20130529184912p:plain

上記のオレンジ色の軌道を指が動いた時にどうなるかというと、赤い丸で囲まれてるように少しでもViewPager上でy軸方向に動いてしまった瞬間に、ViewPagerからイベントは外れて、ListViewにわたってしまいます。1pxもずらさずに横にスワイプした時にした期待した動作をしてくれません。

そんなわけで、ViewPagerを継承して、ViewPagerが動いている間はListViewにイベントが移譲されないように拡張して解決しました。

public class MyViewPager extends ViewPager{
    private ListView listView;

    public MyViewPager(Context context) {
        super(context);
    }
    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setListView(ListView listView) {
        this.listView = listView;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_UP){
            listView.requestDisallowInterceptTouchEvent(false);
        }
        return super.onInterceptTouchEvent(motionEvent);
    }

    @Override
    protected void onPageScrolled(int position, float offset, int offsetPixel) {
        if (offset > 0.01 || 0.99 < offset ) {
            listView.requestDisallowInterceptTouchEvent(true);
        }
        super.onPageScrolled(position, offset, offsetPixel);
    }
}

参考 http://mochi34.blogspot.jp/2012/12/viewpagerscrollview.html

onPageScrolledで、1%以上y軸に動きが無ければ、ListViewに処理を渡さないようにしました。このへんはおこのみで数字を変えれば良いかなぁと思います。 大体これで期待する動作をしてくれるようになりました。 なお詳しくはないんですが、iOSでは標準でこんなふうに動いてくれるようですね。