2つのタブ付きフラグメントを持つ(Sherlock)FragmentActivityがあります。左側のフラグメントはアルバムの写真を表示するGridViewであり、右側のフラグメントは個々の写真を表示するために使用されるViewPagerで構成されています。左側のフラグメントから、画像をスクロールして1つを選択できます。右側のフラグメントにタブ(またはスワイプ)すると画像が表示され、ViewPagerであるため、前または次の画像にスワイプできます。
これは、FragmentActivityが右スワイプをインターセプトして、左タブに戻ることを除いて、うまく機能します。右側のタブにいるときにFragmentActivityがスワイプをインターセプトしないようにしたいと思います。タブ間のスワイプを完全に無効にする必要がある場合は、それで十分です。スワイプを現在のタブ専用にし、タブ間を移動するために使用しないようにしたいだけです。
次の画像は、現在の動作を示しています。右の画像は、右にスワイプするとどうなるかを示しています。ご覧のとおり、左側のタブが表示され始めます。代わりに、スワイプを右のタブにのみ適用して、左のタブを表示せずに画像間をスワイプできるようにします。
ViewPager内でスワイプを制御するソリューションはありますが、タブ付きフラグメント間のスワイプを制御するソリューションはまだ見つかりません。
GridViewフラグメントとViewPagerフラグメントのxmlは次のとおりです。
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:orientation="vertical">
<FrameLayout Android:id="@Android:id/tabcontent"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent">
<GridView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/gridview"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:columnWidth="100dip"
Android:gravity="center"
Android:horizontalSpacing="4dip"
Android:numColumns="auto_fit"
Android:stretchMode="columnWidth"
Android:verticalSpacing="4dip" />
</FrameLayout>
</LinearLayout>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:orientation="vertical">
<Android.support.v4.view.ViewPager xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/pager"
Android:layout_width="fill_parent"
Android:layout_height="0px"
Android:layout_weight="1"/>
</LinearLayout>
ここにViewPagerフラグメントのコード要約があります:
public class FragmentFlash extends SherlockFragment {
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private ViewPager pager = null;
private int pagerPosition;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pagerPosition = 0;
// Gesture detection
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.flash, container, false);
pager = (ViewPager) v.findViewById(R.id.pager);
pager.setOnTouchListener(gestureListener);
return v;
}
class MyGestureDetector extends SimpleOnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 10;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 50;
@Override
public boolean onDown(MotionEvent e) {
return true;//false; make onFling work with fragments
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
else
// right to left swipe
if(distanceX > SWIPE_MIN_DISTANCE) {
if (pagerPosition < imageUrls.length-1)
pager.setCurrentItem(++pagerPosition);
// left to right swipe
} else if (distanceX < -SWIPE_MIN_DISTANCE) {
if (pagerPosition > 0)
pager.setCurrentItem(--pagerPosition);
}
return true;
} catch (Exception e) {
// nothing
}
return false;
}
}
private class ImagePagerAdapter extends PagerAdapter {
private String[] images;
private LayoutInflater inflater;
ImagePagerAdapter(String[] images) {
this.images = images;
inflater = mContext.getLayoutInflater();
}
@Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public void finishUpdate(View container) {
}
@Override
public int getCount() {
return images.length;
}
@Override
public Object instantiateItem(View view, int position) {
final View imageLayout = inflater.inflate(R.layout.item_pager_image, null);
final ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
byte[] image = ;//get byte array from file at images[position];
if (null != image) {
Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
imageView.setImageBitmap(bitmap);
}
((ViewPager) view).addView(imageLayout, 0);
return imageLayout;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void startUpdate(View container) {
}
}
public void pagerPositionSet(int pagerPosition, String[] imageUrls) {
Log.i(Flashum.LOG_TAG, "FragmentFlash pagerPositionSet: " + pagerPosition);
if (pagerPosition >= 0)
this.pagerPosition = pagerPosition;
if (pager != null) {
pager.setAdapter(new ImagePagerAdapter(imageUrls));
pager.setCurrentItem(this.pagerPosition);
}
}
}
これはitem_pager_image.xmlです:
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:padding="1dip" >
<ImageView
Android:id="@+id/image"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:adjustViewBounds="true"
Android:contentDescription="@string/descr_image" />
<ProgressBar
Android:id="@+id/loading"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center"
Android:visibility="gone" />
</FrameLayout>
わかりました、私はついにこれを理解しました。 Laurence Dawsonは正しい方向に進んでいましたが、CustomViewPagerをフラグメントに適用する代わりに、FragmentActivityに適用する必要があります。ご覧のとおり、アクティビティによって管理されるタブの切り替えもViewPagerアダプターです。したがって、アクティビティのxmlは
<TabHost
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@Android:id/tabhost"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<LinearLayout
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<TabWidget
Android:id="@Android:id/tabs"
Android:orientation="horizontal"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_weight="0"/>
<FrameLayout
Android:id="@Android:id/tabcontent"
Android:layout_width="0dp"
Android:layout_height="0dp"
Android:layout_weight="0"/>
<com.Flashum.CustomViewPager
Android:id="@+id/pager"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1"/>
</LinearLayout>
</TabHost>
また、カスタムViewPagerは、コンストラクターによってonInterceptTouchEventがfalseを返すようにすることを除いて、提案どおりです。これにより、FragmentActivityがスワイプに作用するのを防ぎ、フラグメント専用にすることができます。
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = **false**;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
ViewPagerのonInterceptTouchEventメソッドをオーバーライドする必要があります。これを行うには、ViewPagerを拡張するか、次のリンクにアクセスして、これを追加するための優れたチュートリアルを参照してください。
http://blog.svpino.com/2011/08/disabling-pagingswiping-on-Android.html