禁用选项卡FragmentActivity之间的刷卡选项卡、FragmentActivity

2023-09-12 22:53:29 作者:御辞.

我有一个(福尔摩​​斯)FragmentActivity与2标签片段。左边的片段是显示专辑和右片段的图片包括用于查看单个图像的ViewPager的一个GridView。从左边的片段,你可以通过图片滚动和选择之一。跳格(或刷卡)到正确的片段将显示图象和,因为它是一个ViewPager可以刷卡到preceding或下一个图片。

这只是FragmentActivity要拦截正确的刷卡和移动回左侧标签的伟大工程。我想prevent的FragmentActivity截取的挥击的时候我是正确的选项卡上。如果我不得不关闭标签页之间完全刷卡这将是令人满意的。我只是想刷卡专用于当前选项卡,而不是被用于标签之间移动。

下面的图像显示了当前的行为。右边的图像显示,当我做一个向右滑动会发生什么。正如你可以看到左边的标签开始出现。我想刷卡,而不是适用于正确的标签唯一的,这样我可以在图像之间没有刷卡左侧的选项卡出现。

我看到的解决方案来控制ViewPager内刷卡,但还没有找到一个解决方案,以控制标签片段之间刷卡。

下面是XML为GridView片段和ViewPager片段:

 < LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
              机器人:layout_width =FILL_PARENT
              机器人:layout_height =FILL_PARENT
              机器人:方向=垂直>
  <的FrameLayout机器人:ID =@机器人:ID / tabcontent
               机器人:layout_width =FILL_PARENT
               机器人:layout_height =FILL_PARENT>
    < GridView中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
              机器人:ID =@ + ID / GridView控件
              机器人:layout_width =FILL_PARENT
              机器人:layout_height =FILL_PARENT
              机器人:columnWidth中=100dip
              机器人:重力=中心
              机器人:horizo​​ntalSpacing =4dip
              机器人:为numColumns =auto_fit
              机器人:stretchMode =columnWidth中
              机器人:verticalSpacing =4dip/>
  < /的FrameLayout>
< / LinearLayout中>

< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
              机器人:layout_width =FILL_PARENT
              机器人:layout_height =FILL_PARENT
              机器人:方向=垂直>

  < android.support.v4.view.ViewPager的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
                                     机器人:ID =@ + ID /寻呼机
                                     机器人:layout_width =FILL_PARENT
                                     机器人:layout_height =0px
                                     机器人:layout_weight =1/>
< / LinearLayout中>
 
Android Fragment和Activity之间的通信 Frangment生命周期

在ViewPager片段。这里code摘要:

 公共类FragmentFlash扩展SherlockFragment {

   私人GestureDetector gestureDetector;
   View.OnTouchListener gestureListener;
   私人ViewPager寻呼机= NULL;
   私人诠释pagerPosition;

   @覆盖
      公共无效的onCreate(包savedInstanceState){
      super.onCreate(savedInstanceState);
      pagerPosition = 0;
      //手势检测
      gestureDetector =新GestureDetector(新MyGestureDetector());
      gestureListener =新View.OnTouchListener(){
            公共布尔onTouch(视图V,MotionEvent事件){
               返回gestureDetector.onTouchEvent(事件);
            }
         };
      }

   @覆盖
      公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,
                               捆绑savedInstanceState){
      视图V = inflater.inflate(R.layout.flash,集装箱,假);
      寻呼机=(ViewPager)v.findViewById(R.id.pager);
      pager.setOnTouchListener(gestureListener);
      返回伏;
   }

   类MyGestureDetector扩展SimpleOnGestureListener {
      私有静态最终诠释SWIPE_MIN_DISTANCE = 10;
      私有静态最终诠释SWIPE_MAX_OFF_PATH = 250;
      私有静态最终诠释SWIPE_THRESHOLD_VELOCITY = 50;

      @覆盖
         公共布尔onDown(MotionEvent E){
         返回true; //假的;使碎块onFling工作
      }

      @覆盖
         公共布尔onScroll(MotionEvent E1,E2 MotionEvent,浮distanceX,浮distanceY){
         尝试 {
            如果(Math.abs(e1.getY() -  e2.getY())> SWIPE_MAX_OFF_PATH)
               返回false;
            其他
               //从右向左轻扫
               如果(distanceX> SWIPE_MIN_DISTANCE){
                  如果(pagerPosition&所述; imageUrls.length-1)
                     pager.setCurrentItem(++ pagerPosition);
               //从左向右轻扫
               }否则如果(distanceX< -SWIPE_MIN_DISTANCE){
                  如果(pagerPosition大于0)
                     pager.setCurrentItem( -  pagerPosition);
               }
            返回true;
         }赶上(例外五){
            //什么
         }
         返回false;
      }
   }

   私有类ImagePagerAdapter扩展PagerAdapter {

      私有String []的图像;
      私人LayoutInflater充气;

      ImagePagerAdapter(字符串[]的图像){
         this.images =图像;
         充气= mContext.getLayoutInflater();
      }

      @覆盖
         公共无效destroyItem(View容器,INT位置,Object对象){
         ((ViewPager)容器).removeView((查看)对象);
      }

      @覆盖
         公共无效finishUpdate(View容器){
      }

      @覆盖
         公众诠释getCount将(){
         返回images.length;
      }

      @覆盖
         公共对象instantiateItem(查看视图,INT位置){
         最后查看imageLayout = inflater.inflate(R.layout.item_pager_image,NULL);
         最后的ImageView ImageView的=(ImageView的)imageLayout.findViewById(R.id.image);
         最终进度微调=(进度)imageLayout.findViewById(R.id.loading);

         byte []的图像=; //获取字节数组从文件中的图像[位置]
         如果(NULL!=图像){
            点阵位图= BitmapFactory.de codeByteArray(图像,0,image.length);
            imageView.setImageBitmap(位);
         }
         ((ViewPager)视图).addView(imageLayout,0);

         返回imageLayout;
      }

      @覆盖
         公共布尔isViewFromObject(查看视图,Object对象){
         返回view.equals(对象);
      }

      @覆盖
         公共无效restoreState(Parcelable状态,类加载器加载器){
      }

      @覆盖
         公共Parcelable saveState和(){
         返回null;
      }

      @覆盖
         公共无效startUpdate(View容器){
      }
   }

   公共无效pagerPositionSet(INT pagerPosition,字符串[] imageUrls){
      Log.i(Flashum.LOG_TAG,FragmentFlash pagerPositionSet:+ pagerPosition);
      如果(pagerPosition> = 0)
         this.pagerPosition = pagerPosition;
      如果(寻呼机!= NULL){
         pager.setAdapter(新ImagePagerAdapter(imageUrls));
         pager.setCurrentItem(this.pagerPosition);
      }
   }

}
 

这是item_pager_image.xml:

 <的FrameLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT
    机器人:填充=1dip>

    < ImageView的
        机器人:ID =@ + ID /图像
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_gravity =中心
        机器人:adjustViewBounds =真
        机器人:contentDescription =@字符串/ descr_image/>

    <进度
        机器人:ID =@ + ID /加载
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_gravity =中心
        机器人:能见度=水涨船高/>

< /的FrameLayout>
 

解决方案

好吧,我终于想通了这一点。劳伦斯道森是在正确的轨道,但是,代替施加CustomViewPager到片段它需要被施加到FragmentActivity。你看到,翼片,它是由活性管理之间的切换,也是一个ViewPager适配器。因此,XML的活动是

 < TabHost
    的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:ID =@机器人:ID / tabhost
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>

    <的LinearLayout
        机器人:方向=垂直
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent>

        < TabWidget
            机器人:ID =@机器人:ID /标签
            机器人:方向=横向
            机器人:layout_width =match_parent
            机器人:layout_height =WRAP_CONTENT
            机器人:layout_weight =0/>

        <的FrameLayout
            机器人:ID =@机器人:ID / tabcontent
            机器人:layout_width =0dp
            机器人:layout_height =0dp
            机器人:layout_weight =0/>

        < com.Flashum.CustomViewPager
            机器人:ID =@ + ID /寻呼机
            机器人:layout_width =match_parent
            机器人:layout_height =0dp
            机器人:layout_weight =1/>

    < / LinearLayout中>
< / TabHost>
 

和自定​​义ViewPager被作为建议,除了该构造使得它能够引起onInterceptTouchEvent返回false。此$ P $从作用于滑动,以便它可专用于该片段pvents的FragmentActivity!

 公共类CustomViewPager扩展ViewPager {

    私人布尔启用;

    公共CustomViewPager(上下文的背景下,ATTRS的AttributeSet){
        超(背景下,ATTRS);
        this.enabled = **假**;
    }

    @覆盖
    公共布尔的onTouchEvent(MotionEvent事件){
        如果(this.enabled){
            返回super.onTouchEvent(事件);
        }

        返回false;
    }

    @覆盖
    公共布尔onInterceptTouchEvent(MotionEvent事件){
        如果(this.enabled){
            返回super.onInterceptTouchEvent(事件);
        }

        返回false;
    }

    公共无效setPagingEnabled(布尔启用){
        this.enabled =启用;
    }
}
 

I have a (Sherlock)FragmentActivity with 2 tabbed fragments. The left fragment is a GridView that displays pictures of an album and the right fragment consists of a ViewPager that is used to view individual pictures. From the left fragment you can scroll through the pictures and select one. Tabbing (or swiping) over to the right fragment will show the picture and because it is a ViewPager you can swipe to the preceding or the next picture.

This works great except that the FragmentActivity wants to intercept the right swipe and move back to the left tab. I would like to prevent the FragmentActivity from intercepting the swipes when I am on the right tab. If I had to disable swiping between tabs altogether it would be satisfactory. I just want the swiping to be dedicated to the current tab and not be used to move between tabs.

The following images indicate the current behavior. The right image shows what happens when I do a swipe to the right. As you can see the left tab starts to appear. I want the swipe to instead apply to the right tab only so that I can swipe between the images without the left tab appearing.

I see solutions to control swiping within a ViewPager but have yet to find a solution to control swiping between tabbed fragments.

Here is the xml for the GridView fragment and the ViewPager fragment:

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

Here a code summary of the ViewPager fragment:

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);
      }
   }

}

This is the 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>

解决方案

Ok, I finally figured this out. Laurence Dawson was on the right track but instead of applying the CustomViewPager to the fragment it needs to be applied to the FragmentActivity. You see, switching between tabs, which is managed by the activity, is also a ViewPager adaptor. Thus, xml for the activity is

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

And the custom ViewPager is as suggested except that that the constructor enables it to cause onInterceptTouchEvent to return false. This prevents the FragmentActivity from acting on the swipe so that it can be dedicated to the fragment!

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;
    }
}

 
精彩推荐
图片推荐