4

UIScrollView 的 android 中是否有一个等价物,我可以在其中滑动图像。谢谢你。

对不起,我没有更具体。我需要向各个方向滑动。Androids ScrollView 不会这样做。我一直在使用一个有效的 WebView,但它似乎只适用于 4.0 及更高版本。


这就是我想出的。我将 ImageView 放在 WebView 中,并在 ImageView 上分配了 setOnTouchListener。它似乎运作良好。

  web = new WebView(this);
  web.setVerticalScrollBarEnabled(false);
  web.setHorizontalScrollBarEnabled(false);
  web.setBackgroundColor(Color.RED);
  web.setId(100);
  RelativeLayout.LayoutParams layoutForContainer = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutForContainer.height = 300;
    layoutForContainer.width = 300;
    layoutForContainer.addRule(RelativeLayout.CENTER_IN_PARENT);
    web.setLayoutParams(layoutForContainer);     
  layout.addView(web);

  myImageView = new ImageView(this);
  myImageView.setImageResource(R.drawable.myImage); 
  RelativeLayout.LayoutParams layoutForLargeImage = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
  layoutForLargeImage.height = (int) 768;
  layoutForLargeImage.width = (int) 1024;
  myImageView.setLayoutParams(layoutForLargeImage); 
  web.addView(myImageView);

  myImageView.setOnTouchListener(new View.OnTouchListener() {
    float downX, downY;
    int scrollByX, scrollByY;
    public boolean onTouch(View view, MotionEvent event) {
        float currentX, currentY;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                currentX = event.getX();
                currentY = event.getY();
                scrollByX = (int)(downX - currentX);
                scrollByY = (int)(downY - currentY);

                myImageView.scrollBy(scrollByX, scrollByY);
                downX = currentX;
                downY = currentY;

                break;
        }
        return true;
    }
});
4

4 回答 4

2

这个问题差不多一年了,但它是谷歌搜索这个问题的顶部,所以我想我会添加一些细节。

如果您正在寻找可以滚动的通用单向视图,那么使用 Android 内置 ScrollView 的其他答案将可以正常工作。

但是,如果您想要 iOS 的 UIScrollView 的多向方面,则必须设计/使用自定义视图(或使用诸如使用 webview 之类的技巧)。可以在此处的相关问题中找到可以执行此操作的视图的示例实现:

使用水平和垂直平移/拖动和捏缩放查看

然后根据你的口味,你可以根据需要修改它,比如这个实现没有缩放(只是平移):

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.view.*;

public class MultiDirectionPanGroup extends ViewGroup {

    private static final int INVALID_POINTER_ID = 1;
    private int mActivePointerId = INVALID_POINTER_ID;

    private float mPosX;
    private float mPosY;
    private Matrix mTranslateMatrix = new Matrix();
    private Matrix mTranslateMatrixInverse = new Matrix();

    private float mLastTouchX;
    private float mLastTouchY;

    private float mFocusY;

    private float mFocusX;

    private float[] mInvalidateWorkingArray = new float[6];
    private float[] mDispatchTouchEventWorkingArray = new float[2];
    private float[] mOnTouchEventWorkingArray = new float[2];


    public MultiDirectionPanGroup(Context context) {
        super(context);
        mTranslateMatrix.setTranslate(0, 0);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                child.layout(l, t, l+child.getMeasuredWidth(), t + child.getMeasuredHeight());
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.save();
        canvas.translate(mPosX, mPosY);
        super.dispatchDraw(canvas);
        canvas.restore();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        mDispatchTouchEventWorkingArray[0] = ev.getX();
        mDispatchTouchEventWorkingArray[1] = ev.getY();
        mDispatchTouchEventWorkingArray = screenPointsToScaledPoints(mDispatchTouchEventWorkingArray);
        ev.setLocation(mDispatchTouchEventWorkingArray[0],
                mDispatchTouchEventWorkingArray[1]);
        return super.dispatchTouchEvent(ev);
    }

    /**
     * Although the docs say that you shouldn't override this, I decided to do
     * so because it offers me an easy way to change the invalidated area to my
     * likening.
     */
    @Override
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {

        mInvalidateWorkingArray[0] = dirty.left;
        mInvalidateWorkingArray[1] = dirty.top;
        mInvalidateWorkingArray[2] = dirty.right;
        mInvalidateWorkingArray[3] = dirty.bottom;


        mInvalidateWorkingArray = scaledPointsToScreenPoints(mInvalidateWorkingArray);
        dirty.set(Math.round(mInvalidateWorkingArray[0]), Math.round(mInvalidateWorkingArray[1]),
                Math.round(mInvalidateWorkingArray[2]), Math.round(mInvalidateWorkingArray[3]));

        location[0] *= mScaleFactor;
        location[1] *= mScaleFactor;
        return super.invalidateChildInParent(location, dirty);
    }

    private float[] scaledPointsToScreenPoints(float[] a) {
        mTranslateMatrix.mapPoints(a);
        return a;
    }

    private float[] screenPointsToScaledPoints(float[] a){
        mTranslateMatrixInverse.mapPoints(a);
        return a;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        mOnTouchEventWorkingArray[0] = ev.getX();
        mOnTouchEventWorkingArray[1] = ev.getY();

        mOnTouchEventWorkingArray = scaledPointsToScreenPoints(mOnTouchEventWorkingArray);

        ev.setLocation(mOnTouchEventWorkingArray[0], mOnTouchEventWorkingArray[1]);

        final int action = ev.getAction();
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                final float y = ev.getY();

                mLastTouchX = x;
                mLastTouchY = y;

                // Save the ID of this pointer
                mActivePointerId = ev.getPointerId(0);
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                // Find the index of the active pointer and fetch its position
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                final float y = ev.getY(pointerIndex);

                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;

                mPosX += dx;
                mPosY += dy;
                mTranslateMatrix.preTranslate(dx, dy);
                mTranslateMatrix.invert(mTranslateMatrixInverse);

                mLastTouchX = x;
                mLastTouchY = y;

                invalidate();
                break;
            }

            case MotionEvent.ACTION_UP: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_CANCEL: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_POINTER_UP: {
                // Extract the index of the pointer that left the touch sensor
                final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastTouchX = ev.getX(newPointerIndex);
                    mLastTouchY = ev.getY(newPointerIndex);
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                }
                break;
            }
        }
        return true;
    }

}
于 2014-11-04T19:21:15.977 回答
1

显然,像 UIScrollView 这样的选项有很多,(1) 你可以使用 Horizo ​​ntalScrollView (2) 你可以使用Viewpager

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

 <WebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />                   
</RelativeLayout>
于 2013-09-27T06:15:50.573 回答
0

就在这里。使用滚动视图。这是文档

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:stretchColumns="1"
    >
    <!-- everything you already have -->
</LinearLayout>

于 2013-09-27T06:26:31.120 回答
-1

你可以在android中使用

<ScrollView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     >

 </ScrollView>
于 2013-09-27T06:19:09.837 回答