【问题标题】:How to implement zoom, pan and drag on Viewpager in android?如何在android中的Viewpager上实现缩放、平移和拖动?
【发布时间】:2012-07-03 14:19:57
【问题描述】:

我有一个查看器,里面显示视频和图像,请告诉我如何实现缩放、平移、拖动等功能。

在我的 viewpager 里面我有 videoview 和 imageview,现在我想要的是当我执行缩放时它应该缩放两个视图。请告诉我有关此的实施情况。我在论坛上看到的所有地方,我发现人们已经在像 imageview 这样的单个视图上进行缩放平移拖动,但没有直接在 viewpager 上工作,在我的情况下,我必须直接处理 viewpager,以便可以处理其中的所有视图功能像缩放,平移,拖动,无论其中的视图数量如何。帮助表示赞赏。谢谢。

【问题讨论】:

    标签: android


    【解决方案1】:

    对于图片,您可能想看看这个 => android imageView: setting drag and pinch zoom parameters

    从未在 android 上体验过视频,所以我不会在这方面帮助你,但你应该更明确地说明你打算做什么,也许提供一些代码或解释你的应用程序是如何构建的?

    【讨论】:

    • 在我的 viewpager 里面我有 videoview 和 imageview,现在我想要的是当我执行缩放时它应该缩放两个视图。请告诉我有关此的实施情况。我在论坛上看到的所有地方,我发现人们已经在像 imageview 这样的单个视图上进行缩放平移拖动,但没有直接在 viewpager 上工作,在我的情况下,我必须直接处理 viewpager,以便可以处理其中的所有视图功能像缩放,平移,拖动,无论其中的视图数量如何。帮助表示赞赏。谢谢。
    【解决方案2】:

    经过长时间的研发,我得出的结论是,您可以直接在您的 viewpager 所在的父布局上操作事件,例如 Linearlayout 等。请查看此链接:

    http://myandroidnote.blogspot.in/2011/03/pinch-zoom-to-view-completely.html

    它不适用于平移、拖动等所有功能,但您可以通过按钮操作放大、缩小、正常等事件。我已经搜索了很多此类问题,但没有人在任何地方正确解决它。感谢这位朋友:)

    【讨论】:

      【解决方案3】:

      对于缩放和平移,最好的库是 TouchImageView

      ,但是当我们在视图寻呼机上添加这个时,会出现一个问题,当我们缩放图像时滑动图像。即,如果我缩放图像并拖动以查看右侧的另一个缩放部分,由于到视图寻呼机的滑动属性,寻呼机将滑动到下一个图像。如果我们向右滑动也会发生这种情况。所以修复这个问题经过长时间的研发,我终于做了一些修复。为此,我们需要在TouchImageView.java 和 viewpager

      首先我们需要创建一个自定义的 Viewpager

      MyViewPager.java

      package com.example.gallery;
      
      import android.content.Context;
       import android.support.v4.view.ViewPager;
      import android.util.AttributeSet;
      import android.view.MotionEvent;
      
      public class MyViewPager extends ViewPager {
      
      private boolean enabled = true;
      
      public MyViewPager(Context context, AttributeSet attrs) {
          super(context, attrs);
      }
      
      @Override
      public boolean onInterceptTouchEvent(MotionEvent arg0) {
          if(enabled)
              return super.onInterceptTouchEvent(arg0);
      
          return false;
      }
      
      public boolean isEnabled() {
          return enabled;
      }
      
      public void setEnabled(boolean enabled) {
          this.enabled = enabled;
      }
      

      }

      之后我们需要更改 TouchImageView 类修改后的类如下所示

      修改部分 requestDisallowInterceptTouchEvent 添加到触摸事件和 onDoubleTap 部分 也修改,以便用户只有在缩小到其原始或正常位置后才能滑动到下一个图像。放大时用户无法更改当前图像

      private class TouchImageViewListener implements OnTouchListener {
      
          //
          // Remember last point position for dragging
          //
          private PointF last = new PointF();
      
          @Override
          public boolean onTouch(View v, MotionEvent event) {
              mScaleDetector.onTouchEvent(event);
              mGestureDetector.onTouchEvent(event);
              PointF curr = new PointF(event.getX(), event.getY());
      
              if (state == NONE || state == DRAG || state == FLING) {
                  switch (event.getAction()) {
                  case MotionEvent.ACTION_DOWN:
                      last.set(curr);
                      if (fling != null)
                          fling.cancelFling();
                      setState(DRAG);
                          //Modified Portion  
      
                getParent().requestDisallowInterceptTouchEvent(true);
                      break;
      
                  case MotionEvent.ACTION_MOVE:
                      if (state == DRAG) {
                          float deltaX = curr.x - last.x;
                          float deltaY = curr.y - last.y;
                          float fixTransX = getFixDragTrans(deltaX, viewWidth,
                                  getImageWidth());
                          float fixTransY = getFixDragTrans(deltaY, viewHeight,
                                  getImageHeight());
                          matrix.postTranslate(fixTransX, fixTransY);
                          if (deltaX == 0 || normalizedScale == 1.0)
                          //Modified Portion  
      
                 getParent().requestDisallowInterceptTouchEvent(false)
                          else
                                     getParent().requestDisallowInterceptTouchEvent(true);
                          fixTrans();
                          last.set(curr.x, curr.y);
                      }
                      break;
      
                  case MotionEvent.ACTION_UP:
                  //Modified Portion  
      
                     getParent().requestDisallowInterceptTouchEvent(false)
      
                      break;
                  case MotionEvent.ACTION_POINTER_UP:
                      setState(NONE);
                      break;
                  }
              }
      
              setImageMatrix(matrix);
              //
              // indicate event was handled
              //
              return true;
          }
      }//requestDisallowInterceptTouchEvent is Added When Touch Lister Occurs While Zoomed In
      
      .......
      private class GestureListener extends
              GestureDetector.SimpleOnGestureListener {
      
          @Override
          public boolean onSingleTapConfirmed(MotionEvent e) {
              return performClick();
          }
      
          @Override
          public void onLongPress(MotionEvent e) {
              performLongClick();
          }
      
          @Override
          public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                  float velocityY) {
              if (fling != null) {
                  //
                  // If a previous fling is still active, it should be cancelled
                  // so that two flings
                  // are not run simultaenously.
                  //
                  fling.cancelFling();
              }
              fling = new Fling((int) velocityX, (int) velocityY);
              compatPostOnAnimation(fling);
              return super.onFling(e1, e2, velocityX, velocityY);
          }
      
          @Override
          public boolean onDoubleTap(MotionEvent e) {
              boolean consumed = false;
      
      //Modified Portion
              if (state == NONE) {
                  float targetZoom = (normalizedScale == minScale) ? maxScale
                          : minScale;
                  DoubleTapZoom doubleTap = new DoubleTapZoom(targetZoom,
                          e.getX(), e.getY(), false);
                  compatPostOnAnimation(doubleTap);
                  consumed = true;
              }
              else
              {
                  float targetZoom = (normalizedScale == minScale) ? maxScale
                          : minScale;
                  DoubleTapZoom doubleTap = new DoubleTapZoom(targetZoom,
                          e.getX(), e.getY(), false);
                  compatPostOnAnimation(doubleTap);
              }
              return consumed;
          }
      }//Allow User To Double Tap To Orginal Position So that only he can Swipe to next image
      

      Here下载TouchImageView并修改以上部分

      FullScreenImageAdapter.java

      package com.example.gallery;
      
      
      
      public class FullScreenImageAdapter extends PagerAdapter {
      
      private Activity _activity;
      private String[] mStrings;
      private LayoutInflater inflater;
      ImageLoader im;
      
      
      // constructor
      public FullScreenImageAdapter(Activity activity, String[] mStrings) {
          this._activity = activity;
          this.mStrings = mStrings;
      
          im = new ImageLoader(_activity);
      }
      
      @Override
      public int getCount() {
          return this.mStrings.length;
      }
      
      @Override
      public boolean isViewFromObject(View view, Object object) {
          return view == ((RelativeLayout) object);
      }
      
      @Override
      public Object instantiateItem(ViewGroup container, int position) {
          TouchImageView imgDisplay;
          final Button btnClose;
      
          inflater = (LayoutInflater) _activity
                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          View viewLayout = inflater.inflate(R.layout.layout_fullscreen_image,
                  container, false);
          RelativeLayout parentview = (RelativeLayout) viewLayout
                  .findViewById(R.id.rel);
          imgDisplay = (TouchImageView) viewLayout.findViewById(R.id.imgDisplay);
          btnClose = (Button) viewLayout.findViewById(R.id.btnClose);
      
           im.DisplayImage(mStrings[position], imgDisplay);
      
          // close button click event
          btnClose.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  _activity.finish();
              }
          });
      
          ((ViewPager) container).addView(viewLayout);
          /**
           * Setting the object for animation
           * */
      
      
          return viewLayout;
      }
      
      @Override
      public void destroyItem(ViewGroup container, int position, Object object) {
          ((ViewPager) container).removeView((RelativeLayout) object);
      
      }
      

      }

      MainActivity.java

      package com.example.gallery;
      
      
      
      
      
      public class MainActivity extends Activity {
      
      private FullScreenImageAdapter adapter;
      private MyViewPager viewPager;
      private String[] mStrings = {
              "http://3rdbillion.net/wp-content/uploads/2013/12/9039b649b7cd0ee7f418e55416a8ea204.jpg",
                  "http://images.tentebranda.org/wp-content/uploads/animal-images_5514_1.jpg",
                  "http://3rdbillion.net/wp-content/uploads/2013/12/f6aa5d04531f8ff9416ace6e273405304.jpg",
                  "http://3rdbillion.net/wp-content/uploads/2013/12/fcbc6aaa7ccd1ebaea80f36bfad3c8f74.jpg"};
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_fullscreen_view);
      
          viewPager = (MyViewPager) findViewById(R.id.pager);
      
      
      
          adapter = new FullScreenImageAdapter(MainActivitys.this, mStrings);
      
      
          viewPager.setAdapter(adapter);
          viewPager.setPageMargin(30);
          // displaying selected image first
          viewPager.setCurrentItem(position);
      }
      }
      

      图像使用延迟加载从 Web 显示在此示例中,我使用 LAzyLoad library

      请下载并将其添加到您的项目中

      最后是 Xml 文件

      layout_fullscreen_image.xml

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/rel" >
      
      <!-- <YourPackagename where TouchImageView.java is Placed.TouchImageView
          android:id="@+id/imgDisplay"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:scaleType="fitCenter" />Example is given below My TouchImageView.java is placed in the com.example.gallery package
      -->
      
        <com.example.gallery.TouchImageView
          android:id="@+id/imgDisplay"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:scaleType="fitCenter" />
      
      <Button
          android:id="@+id/btnClose"
          android:layout_width="wrap_content"
          android:layout_height="30dp"
          android:layout_alignParentRight="true"
          android:layout_alignParentTop="true"
          android:layout_marginRight="15dp"
          android:layout_marginTop="15dp"
          android:paddingTop="2dp"
          android:paddingBottom="2dp"
          android:background="@drawable/ic_launcher"
          android:textColor="#ffffff"
          android:paddingLeft="10dp"
          android:paddingRight="10dp"
          android:text="Close" />
      

      activity_fullscreen_view

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"
      android:background="#33BBFFFF" >
      <!--<YourPackagename where MyViewPager.java is Placed.MyViewPager
          android:id="@+id/pager"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" />Example is given below My MyViewPager.java is placed in the com.example.gallery package-->
      
      <com.example.gallery.MyViewPager
          android:id="@+id/pager"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" />
      
      </LinearLayout>
      

      在清单文件中添加 Internet 权限和写入存储权限即可完成

      <uses-permission android:name="android.permission.INTERNET"/>
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
      

      对于从 Sd 卡显示图像仅替换延迟加载部分并添加必要的文件以从 Sd 卡显示图像并设置适配器

      -----------------更新-----

      TouchImageview 的新链接是here

      【讨论】:

        【解决方案4】:

        由于此线程中的所有答案都相当陈旧,我将在此处发布我的调查结果。我终于找到了Subsampling Scale Image View 库,它可以与 Android 支持包中的标准 ViewPager 一起使用,无需任何自定义。值得一试。

        【讨论】:

        • 过度宣传特定产品/资源可能会被社区视为垃圾邮件。看看help center,特别是What kind of behavior is expected of users? 的最后一部分:避免公开的自我推销。您可能还对How do I advertise on Stack Overflow? 感兴趣。你已经提到了这个产品herehere
        • @Tunaki 我提到的图书馆不是我的图书馆。我与它的作者或类似的东西没有任何关系。我什至没有为这个图书馆做出贡献。我没有兴趣推广它,除了帮助其他人找到它并解决他们的问题。因为我花了几个小时尝试上面提到的库。尤其是因为公认的答案说缩放图像的最佳库是 TouchImageView,但在我看来这不是实际信息。
        • 很公平,但您应该尝试通过包含其用法示例来改进您的答案。此外,您还发布了 2 个类似的其他答案:如果问题重复,您应该投票关闭。
        猜你喜欢
        • 1970-01-01
        • 2013-12-11
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        • 2012-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多