【问题标题】:Android Gallery zoom in/outAndroid 图库放大/缩小
【发布时间】:2012-07-13 04:32:21
【问题描述】:

您好,我正在使用图库小部件来显示从 Internet 下载的图像。

要显示几张图像,我希望在人们在屏幕上上下滑动时进行逐渐缩放。我知道如何实现触摸事件唯一我不知道如何使整个画廊视图逐渐增长。我不想放大一张图片我希望整个画廊逐渐放大/缩小。

EDIT3:我设法缩放画廊的可见部分,但问题是我需要找到一种方法让画廊了解它并更新它的其他孩子。

如果 3 张图片可见,然后您开始缩放并且画廊确实变小了,图片也会变小,但 在这种情况下我希望更多图片可见,但我不这样做不知道如何达到这个预期的效果。这是完整的代码:

public class Gallery1 extends Activity implements OnTouchListener {

private static final String TAG = "GalleryTest";
private float zoom=0.0f;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
Gallery g;
LinearLayout layout2;
private ImageAdapter ad;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gallery_1);
    layout2=(LinearLayout) findViewById(R.id.layout2);

    // Reference the Gallery view
    g = (Gallery) findViewById(R.id.gallery);
    // Set the adapter to our custom adapter (below)
    ad=new ImageAdapter(this);
    g.setAdapter(ad);


    layout2.setOnTouchListener(this);

}


public void zoomList(boolean increase) {
    Log.i(TAG, "startig animation");


    AnimatorSet set = new AnimatorSet();
    set.playTogether(

        ObjectAnimator.ofFloat(g, "scaleX", zoom),
        ObjectAnimator.ofFloat(g, "scaleY", zoom)

    );
    set.addListener(new AnimatorListener() {

        @Override
        public void onAnimationStart(Animator animation) {


        }

        @Override
        public void onAnimationRepeat(Animator animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationEnd(Animator animation) {

        }

        @Override
        public void onAnimationCancel(Animator animation) {
            // TODO Auto-generated method stub

        }
    });
    set.setDuration(100).start();


}


public class ImageAdapter extends BaseAdapter {
    private static final int ITEM_WIDTH = 136;
    private static final int ITEM_HEIGHT = 88;

    private final int mGalleryItemBackground;
    private final Context mContext;

    private final Integer[] mImageIds = {
            R.drawable.gallery_photo_1,
            R.drawable.gallery_photo_2,
            R.drawable.gallery_photo_3,
            R.drawable.gallery_photo_4,
            R.drawable.gallery_photo_5,
            R.drawable.gallery_photo_6,
            R.drawable.gallery_photo_7,
            R.drawable.gallery_photo_8
    };

    private final float mDensity;

    public ImageAdapter(Context c) {
        mContext = c;
        // See res/values/attrs.xml for the <declare-styleable> that defines
        // Gallery1.
        TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
        mGalleryItemBackground = a.getResourceId(
                R.styleable.Gallery1_android_galleryItemBackground, 1);
        a.recycle();

        mDensity = c.getResources().getDisplayMetrics().density;
    }

    public int getCount() {
        return mImageIds.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {
            convertView = new ImageView(mContext);

            imageView = (ImageView) convertView;
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            imageView.setLayoutParams(new Gallery.LayoutParams(
                    (int) (ITEM_WIDTH * mDensity + 0.5f),
                    (int) (ITEM_HEIGHT * mDensity + 0.5f)));

        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(mImageIds[position]);

        return imageView;
    }
}

public boolean onTouch(View v, MotionEvent event) {

    if (event.getAction() == MotionEvent.ACTION_MOVE
            && event.getPointerCount() > 1) {
        midPoint(mid, event);

        if(mid.y > start.y){

            Log.i(TAG, "Going down (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); // going down so increase
            if ((Math.abs(mid.y - start.y) > 10) && (zoom<2.5f)){

                zoom=zoom+0.1f;
                midPoint(start, event);
                zoomList(true);


            }
            return true;
        }else if(mid.y < start.y){

            Log.i(TAG, "Going up (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); //smaller
            if ((Math.abs(mid.y - start.y) > 10) &&(zoom>0.1)){

                midPoint(start, event);
                zoom=zoom-0.1f;
                zoomList(false);

            }
            return true;
        }

    }

    else if (event.getAction() == MotionEvent.ACTION_POINTER_DOWN) {
        Log.e(TAG, "Pointer went down: " + event.getPointerCount());
        return true;
    }
    else if (event.getAction() == MotionEvent.ACTION_UP) {
        Log.i(TAG, "Pointer going up");
        return true;
    }
    else if (event.getAction() == MotionEvent.ACTION_DOWN) {
        Log.i(TAG, "Pointer going down");
        start.set(event.getX(), event.getY());
        return true;
    }

     return false;
       // indicate event was handled or not
   }

private void midPoint(PointF point, MotionEvent event) {
    float x = event.getX(0) + event.getX(1);
    float y = event.getY(0) + event.getY(1);
    point.set(x / 2, y / 2);
 }

我意识到我可能不得不扩展 Gallery 甚至另一个 View 组或创建我自己的类,但我不知道从哪里开始:哪种方法使用负责缩放的方法...

EDIT4:我不知道他的问题是否足够清楚。以下是状态示例:

状态一:初始状态,我们有 3 张图像在视图中

状态 2:我们检测到两根手指向上的垂直触摸 = 我们必须缩小

状态 3:我们开始缩放 = 动画在画廊或孩子身上???

状态 4:画廊检测到它的 3 个孩子更小

状态 5:画廊根据新的可用空间添加 1 个/多个孩子

最后更新: 感谢所有发布的内容,但我终于得出了一个结论,那就是根本不使用画廊: 1. 已弃用 2. 对于我的情况,它的可定制性不够

如果您想一次为多个图像制作动画,您可能需要考虑使用 OpenGl,我正在使用 libgdx 库: https://github.com/libgdx/libgdx

【问题讨论】:

    标签: android image listview zooming


    【解决方案1】:

    这是解决方案 将 android 中的图库组件与手势图像库集成 gesture-imageView

    这里是完整的示例代码 SampleCode

    【讨论】:

    • 请不要跨多个问题复制和粘贴答案。此外,这里通常不赞成仅链接的答案,那么您能否更详细地解释为什么链接的 GitHub 项目将解决手头的确切问题?最后,我们希望您可以将示例代码放在 MediaFire 以外的其他位置,因为这些链接很快就会失效。
    【解决方案2】:

    你也可以为画廊做图像缩放捏选项。 通过使用以下代码行:

    您可以下载示例。

    https://github.com/alvinsj/android-image-gallery/downloads

    我希望这个例子对你有所帮助..如果你有任何疑问可以问我.....

    【讨论】:

      【解决方案3】:

      以下 ScalingGallery 实施可能会有所帮助。
      此图库子类覆盖执行缩放的 getChildStaticTransformation(View child, Transformation t) 方法。您可以进一步自定义缩放参数以满足您自己的需求。

      请注意 ScalingGalleryItemLayout.java 类。这是必要的,因为在您对子视图执行缩放操作后,它们的命中框不再有效,因此必须使用 getChildStaticTransformation(View child, Transformation t) 方法。

      这是通过将每个画廊项目包装在一个扩展 LinearLayoutScalingGalleryItemLayout 中来完成的。同样,如果 LinearLayout 不能满足您对画廊项目进行布局的需求,您可以对其进行自定义以满足您自己的需求。

      文件:/src/com/example/ScalingGallery.java

      /**
       * A Customized Gallery component which alters the size and position of its items based on their position in the Gallery.
       */
      public class ScalingGallery extends Gallery {
      
          public static final int ITEM_SPACING = -20;
      
          private static final float SIZE_SCALE_MULTIPLIER = 0.25f;
          private static final float ALPHA_SCALE_MULTIPLIER = 0.5f;
          private static final float X_OFFSET = 20.0f;
      
          /**
           * Implemented by child view to adjust the boundaries after it has been matrix transformed. 
           */
          public interface SetHitRectInterface {
              public void setHitRect(RectF newRect); 
          }
      
          /**
           * @param context
           *            Context that this Gallery will be used in.
           * @param attrs
           *            Attributes for this Gallery (via either xml or in-code)
           */
          public ScalingGallery(Context context, AttributeSet attrs) {
              super(context, attrs);
              setStaticTransformationsEnabled(true);
              setChildrenDrawingOrderEnabled(true);
          }
      
          /**
           * {@inheritDoc}
           * 
           * @see #setStaticTransformationsEnabled(boolean)
           *
           * This is where the scaling happens.
           */
          protected boolean getChildStaticTransformation(View child, Transformation t) {
      
              child.invalidate();
      
              t.clear();
              t.setTransformationType(Transformation.TYPE_BOTH);
      
              // Position of the child in the Gallery (... +2  +1  0  -1  -2 ... 0 being the middle)
              final int childPosition = getSelectedItemPosition() - getPositionForView(child);
              final int childPositionAbs = (int) Math.abs(childPosition);
      
              final float left = child.getLeft();
              final float top = child.getTop();
              final float right = child.getRight();
              final float bottom = child.getBottom();
      
              Matrix matrix = t.getMatrix();
              RectF modifiedHitBox = new RectF();
      
              // Change alpha, scale and translate non-middle child views.
              if (childPosition != 0) {
      
                  final int height = child.getMeasuredHeight();
                  final int width = child.getMeasuredWidth();
      
                  // Scale the size.
                  float scaledSize = 1.0f - (childPositionAbs * SIZE_SCALE_MULTIPLIER);
                  if (scaledSize < 0) {
                      scaledSize = 0;
                  }
                  matrix.setScale(scaledSize, scaledSize);
      
                  float moveX = 0;
                  float moveY = 0;
      
                  // Moving from right to left -- linear move since the scaling is done with respect to top-left corner of the view.
                  if (childPosition < 0) {
                      moveX = ((childPositionAbs - 1) * SIZE_SCALE_MULTIPLIER * width) + X_OFFSET;
                      moveX *= -1;
      
                  } else { // Moving from left to right -- sum of the previous positions' x displacements.
      
                      // X(n) = X(0) + X(1) + X(2) + ... + X(n-1)
                      for (int i = childPositionAbs; i > 0; i--) {
                          moveX += (i * SIZE_SCALE_MULTIPLIER * width);
                      }
                      moveX += X_OFFSET;
                  }
      
                  // Moving down y-axis is linear.
                  moveY = ((childPositionAbs * SIZE_SCALE_MULTIPLIER * height) / 2);
      
                  matrix.postTranslate(moveX, moveY);
      
                  // Scale alpha value.
                  final float alpha = (1.0f / childPositionAbs) * ALPHA_SCALE_MULTIPLIER;
                  t.setAlpha(alpha);
      
                  // Calculate new hit box.  Since we moved the child, the hitbox is no longer lined up with the new child position.
                  final float newLeft = left + moveX;
                  final float newTop = top + moveY;
                  final float newRight = newLeft + (width * scaledSize);
                  final float newBottom = newTop + (height * scaledSize);
                  modifiedHitBox = new RectF(newLeft, newTop, newRight, newBottom);
              } else {
                  modifiedHitBox = new RectF(left, top, right, bottom);
              }
      
              // update child hit box so you can tap within the child's boundary
              ((SetHitRectInterface) child).setHitRect(modifiedHitBox);
      
              return true;
          }
      
          @Override
          protected void onLayout(boolean changed, int l, int t, int r, int b) {
      
              // Helps to smooth out jittering during scrolling.
              // read more - http://www.unwesen.de/2011/04/17/android-jittery-scrolling-gallery/
              final int viewsOnScreen = getLastVisiblePosition() - getFirstVisiblePosition();
              if (viewsOnScreen <= 0) {
                  super.onLayout(changed, l, t, r, b);
              }
          }
      
          private int mLastDrawnPosition;
      
          @Override
          protected int getChildDrawingOrder(int childCount, int i) {
      
              //Reset the last position variable every time we are starting a new drawing loop
              if (i == 0) {
                  mLastDrawnPosition = 0;
              }
      
              final int centerPosition = getSelectedItemPosition() - getFirstVisiblePosition();
      
              if (i == childCount - 1) {
                  return centerPosition;
              } else if (i >= centerPosition) {
                  mLastDrawnPosition++;
                  return childCount - mLastDrawnPosition;
              } else {
                  return i;
              }
          }
      }
      

      文件:/src/com/example/ScalingGalleryItemLayout.java

      public class ScalingGalleryItemLayout extends LinearLayout implements SetHitRectInterface {
      
          public ScalingGalleryItemLayout(Context context) {
              super(context);
          }
      
          public ScalingGalleryItemLayout(Context context, AttributeSet attrs) {
              super(context, attrs);
          }
      
          public ScalingGalleryItemLayout(Context context, AttributeSet attrs, int defStyle) {
              super(context, attrs, defStyle);
          }
      
          private Rect mTransformedRect;
      
          @Override
          public void setHitRect(RectF newRect) {
      
              if (newRect == null) {
                  return;
              }
      
              if (mTransformedRect == null) {
                  mTransformedRect = new Rect();
              }
      
              newRect.round(mTransformedRect);
          }
      
          @Override
          public void getHitRect(Rect outRect) {
      
              if (mTransformedRect == null) {
                  super.getHitRect(outRect);
              } else {
                  outRect.set(mTransformedRect);
              }
          }
      }
      

      文件:/res/layout/ScaledGalleryItemLayout.xml

      <?xml version="1.0" encoding="utf-8"?>
      <com.example.ScalingGalleryItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/gallery_item_layout"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_gravity="center"
          android:gravity="center"
          android:orientation="vertical"
          android:padding="5dp" >
      
          <ImageView
              android:id="@+id/gallery_item_image"
              android:layout_width="360px"
              android:layout_height="210px"
              android:layout_gravity="center"
              android:antialias="true"
              android:background="@drawable/gallery_item_button_selector"
              android:cropToPadding="true"
              android:padding="35dp"
              android:scaleType="centerInside" />
      
          <TextView
              android:id="@+id/gallery_item_text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:textColor="@drawable/white"
              android:textSize="30sp" />
      
      </com.example.ScalingGalleryItemLayout>
      

      【讨论】:

      • 感谢 Akos 的回答。我已经尝试过了,但是当我在他的画廊上使用动画时,结果和以前一样:可见的是 schrinks,但没有绘制新的视图。如果我将动画仅应用于一个视图,则该视图只会缩放。如果我使用 scaleX/scaleY 相同的东西......我决定创建自己的 Surfaceview 并绘制位图
      • 请将您的完整代码放在这里...我急需...提前致谢!
      • @Akos Cz 我尝试了你的解决方案,但它不起作用。得到 ArrayIndexOutOfBoundsException 错误。
      【解决方案4】:

      要在动画完成后保持动画状态,只需对动画执行以下操作:

      youranim.setFillAfter(true);
      

      编辑:

      在我的项目中,我使用这种方法,我认为它对你有帮助:

      http://developer.sonymobile.com/wp/2011/04/12/how-to-take-advantage-of-the-pinch-to-zoom-feature-in-your-xperia%E2%84%A2-10-apps-part-1/

      【讨论】:

      • 你说得对,但我使用的是 animSet,所以不得不将它应用于整个集合,但这并不能解决我的问题:动画重新调整了画廊,但不是以我想要的方式。当画廊变小时,我希望它显示更多图像,但在我的情况下,它仍然只显示一张图像,所以整个布局只会缩小
      • 是的,我已经看到该代码很棒,但是有很多例子可以处理图像缩放问题是我需要同时缩放多个图像,并且画廊应该调整自身大小以显示根据缩放级别的一张或多张图片。
      猜你喜欢
      • 1970-01-01
      • 2011-07-18
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 2016-05-24
      • 1970-01-01
      • 2013-03-20
      • 1970-01-01
      相关资源
      最近更新 更多