android scrollview下的textview如何实现手势缩放并且可以长按出现上下文菜单

自己先自定义了一个scrollview,然后在xml相关的activity中写了一个ontouchevent,最后出现的结果是手势缩放与长按出现上下文菜单总不能同时实现!
代码如下:
自定义scrollview:
@Override
public boolean onInterceptTouchEvent( MotionEvent event)

{

        return super.onInterceptTouchEvent(event);

}

@Override
public boolean onTouchEvent(MotionEvent event)
{
    super.onTouchEvent(event);
    if(event.getPointerCount()==2)
    {
        return false;
    }
    else
    {
        return true;
    }
}
    与xml相关的activity
    手势缩放
    public boolean onTouchEvent(MotionEvent event) {
    int nCnt = event.getPointerCount();
    int n = event.getAction();
    if( (event.getAction()&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN && 2 == nCnt)//2表示两个手指</span>
    {
        int xlen = Math.abs((int)event.getX(0) - (int)event.getX(1));
        int ylen = Math.abs((int)event.getY(0) - (int)event.getY(1));
        nLenStart = Math.sqrt((double)xlen*xlen + (double)ylen * ylen);
    }else if( (event.getAction()&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP  && 2 == nCnt)
    {
        int xlen = Math.abs((int)event.getX(0) - (int)event.getX(1));
        int ylen = Math.abs((int)event.getY(0) - (int)event.getY(1));
        double nLenEnd = Math.sqrt((double)xlen*xlen + (double)ylen * ylen);
        DisplayMetrics dm = getResources().getDisplayMetrics();
        float value = dm.scaledDensity;
        if(nLenEnd > nLenStart)//通过两个手指开始距离和结束距离,来判断放大缩小
        {
            text.setTextSize((text.getTextSize()+(float)(0.1*(nLenEnd-nLenStart)))/value);
            Size=text.getTextSize();
            Toast.makeText(getApplicationContext(), "放大", 2000).show();
        }
        else
        {
            text.setTextSize((text.getTextSize()-(float)(0.1*(nLenStart-nLenEnd)))/value);
            Size=text.getTextSize();
            Toast.makeText(getApplicationContext(), "缩小",2000).show();
        }
    }
    return super.onTouchEvent(event);
            }
            出现上下文菜单:
            public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

    if(v==text) {

        //v.getParent().requestDisallowInterceptTouchEvent(false);
        //if(menu.size()==0){
        menu.add(0, MENU_COPY, 0, "复制");
    }
    super.onCreateContextMenu(menu, v, menuInfo);
}

    出现的问题时,当自定义的onInterceptTouchEvent返回true时,缩放正常,没办法长按出上下文菜单,当其返回super.onInterceptTouchEvent(event)时,能出现上下文菜单,不能正常缩放!自己大概知道是什么问题,应该是手势拦截问题,又不是很清楚,希望各位大神能够指出问题,并能给个解决方案,或做过类似的demo可以给发一份,非常感谢!

1个回答

分享一个以前做过的手势缩放 demo,希望对题主有帮助。给题主推荐一个技术干货的APP,里面有不少 Android 相关的学习资源,稀土掘金 http://gold.xitu.io/app

主界面的activity:

 package test;
import com.agehua.drag.R;

import android.app.Activity; 
import android.content.Context;
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Matrix; 
import android.graphics.PointF; 
import android.hardware.SensorManager; 
import android.os.Bundle; 
import android.util.DisplayMetrics;
import android.util.FloatMath; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.View.OnTouchListener; 
import android.widget.Button; 
import android.widget.ImageView; 

public class Touch extends Activity implements OnTouchListener, OnClickListener { 
    private static final String TAG = "Touch" ; 

    // These matrices will be used to move and zoom image 
    Matrix matrix = new Matrix(); 
    Matrix savedMatrix = new Matrix(); 
    PointF start = new PointF(); 
    PointF mid = new PointF(); 
    float  oldDist; 
    private ImageView view; 
    private MyScrollView scrollView;
    private Button zoomIn, zoomOut; 
    //button zoom 
    private float scaleWidth = 1; 
    private float scaleHeight = 1; 
    private Bitmap bmp, zoomedBMP; 

    private static final double ZOOM_IN_SCALE = 1.25;//放大系数 
    private static final double ZOOM_OUT_SCALE = 0.8;//缩小系数 
    // We can be in one of these 3 states 
    static final int NONE = 0; 
    static final int DRAG = 1; 
    static final int ZOOM = 2; 
    int mode = NONE; 

    int bmpWidth,bmpHeight;
    int imageHeight, imageWidth;

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main1); 
        view = (ImageView) findViewById(R.id.imageView); 
        view.setOnTouchListener(this); 
        scrollView = (MyScrollView)findViewById(R.id.scrollview);

        zoomIn = (Button)findViewById(R.id.btn_zoom_in);
        zoomOut = (Button)findViewById(R.id.btn_zoom_out);
        zoomOut.setOnClickListener(this);
        zoomIn.setOnClickListener(this);
        //取得drawable中图片,放大,缩小,多点触摸的作用对象 
        bmp = BitmapFactory.decodeResource(Touch.this.getResources(), R.drawable.aaa); 
        bmpWidth = bmp.getWidth(); 
        bmpHeight = bmp.getHeight(); 
    } 


    public boolean onTouch(View v, MotionEvent event) { 
        // Handle touch events here... 
        ImageView view = (ImageView) v; 

//      imageWidth = v.getWidth();//屏幕宽度(像素数)
//      imageHeight = v.getHeight();

        // Handle touch events here... 
        switch (event.getAction() & MotionEvent.ACTION_MASK) { 
        //设置拖拉模式 
        case MotionEvent.ACTION_DOWN: 
            savedMatrix.set(matrix); 
            start.set(event.getX(), event.getY()); 
            Log.d(TAG, "mode=DRAG" ); 
            mode = DRAG; 
            break; 

        case MotionEvent.ACTION_UP: 
        case MotionEvent.ACTION_POINTER_UP: 
            mode = NONE; 
            Log.d(TAG, "mode=NONE" ); 
            break; 
            //设置多点触摸模式 
        case MotionEvent.ACTION_POINTER_DOWN: 
            oldDist = spacing(event); 
            //          originalDist = oldDist;
            Log.d(TAG, "oldDist=" + oldDist); 
            if (oldDist > 10f) { 
                savedMatrix.set(matrix); 
                midPoint(mid, event); 
                mode = ZOOM; 
                Log.d(TAG, "mode=ZOOM" ); 
            } 
            break; 
            //若为DRAG模式,则点击移动图片 
        case MotionEvent.ACTION_MOVE: 
            if (mode == DRAG) { 
                matrix.set(savedMatrix); 
                // 设置位移 
                matrix.postTranslate(event.getX() - start.x, 
                        event.getY() - start.y); 
            } 
            //若为ZOOM模式,则多点触摸缩放 
            else if (mode == ZOOM) { 
                float newDist = spacing(event); 
                Log.d(TAG, "newDist=" + newDist); 
                if (newDist > 10f) { 
                    matrix.set(savedMatrix); 
                    float scale = newDist / oldDist; 
                    //设置缩放比例和图片中点位置 
                    matrix.postScale(scale, scale, mid.x, mid.y); 
                } 
            } 
            break; 
        } 

        // Perform the transformation 
        view.setImageMatrix(matrix); 

        return true; // indicate event was handled 
    } 



    //计算移动距离 
    private float spacing(MotionEvent event) { 
        float x = event.getX(0) - event.getX(1); 
        float y = event.getY(0) - event.getY(1); 
        return FloatMath.sqrt(x * x + y * y); 
    } 
    //计算中点位置 
    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); 
    } 

    //放大,缩小按钮点击事件 
    @Override 
    public void onClick(View v) { 
        if(v == zoomIn){ 
            enlarge(); 
        }else if (v == zoomOut) { 
            small(); 
        } 
    } 

    //按钮点击缩小函数 
    private void small() { 
        int bmpWidth = bmp.getWidth(); 
        int bmpHeight = bmp.getHeight(); 

        scaleWidth = (float) (scaleWidth * ZOOM_OUT_SCALE); 
        scaleHeight = (float) (scaleHeight * ZOOM_OUT_SCALE); 

        Matrix matrix = new Matrix(); 
        matrix.postScale(scaleWidth, scaleHeight); 
        zoomedBMP = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, 
                true); 
        view.setImageBitmap(zoomedBMP); 
    } 

    //按钮点击放大函数 
    private void enlarge() { 
        try { 
            int bmpWidth = bmp.getWidth(); 
            int bmpHeight = bmp.getHeight(); 

            scaleWidth = (float) (scaleWidth * ZOOM_IN_SCALE); 
            scaleHeight = (float) (scaleHeight * ZOOM_IN_SCALE); 

            Matrix matrix = new Matrix(); 
            matrix.postScale(scaleWidth, scaleHeight); 
            zoomedBMP = Bitmap.createBitmap(bmp, 0, 0, bmpWidth, bmpHeight, matrix, 
                    true); 
            view.setImageBitmap(zoomedBMP); //存在内存溢出问题

        } catch (Exception e) { 
            //can't zoom because of memory issue, just ignore, no big deal 
        } 
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        if (null != bmp && !bmp.isRecycled()) {
            bmp.recycle();
        }
        System.gc();
        super.onDestroy();
    } 


}

scrollview部分的代码:

 package test;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ScrollView;

public class MyScrollView extends ScrollView {
    private boolean canScroll;

    private GestureDetector mGestureDetector;
    View.OnTouchListener mGestureListener;

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureDetector = new GestureDetector(context, new YScrollDetector());
        canScroll = true;
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if(ev.getAction() == MotionEvent.ACTION_UP)
            canScroll = true;
        return super.onInterceptTouchEvent(ev) && mGestureDetector.onTouchEvent(ev);
    }

    public class YScrollDetector extends SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if(canScroll)
                if (Math.abs(distanceY) >= Math.abs(distanceX))
                    canScroll = true;
                else
                    canScroll = false;
            return canScroll;
        }
    }
}

main1.xml内容为:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center" 
    android:orientation="vertical">

    <test.MyScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal"
        android:orientation="vertical" 
        android:layout_weight="1"
        android:id="@+id/scrollview">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="matrix"
            android:src="@drawable/aaa" />
    </test.MyScrollView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_horizontal" >

        <Button
            android:id="@+id/btn_zoom_in"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="放大" />

        <Button
            android:id="@+id/btn_zoom_out"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="缩小" />
    </LinearLayout>

</LinearLayout>

注意问题:1.scrollview的layout_width属性最好设置为match_parent,如果设置为wrap_content,图片会滑动不到屏幕边界。
2.imageview的scaleType属性一定要设置为matrix(矩阵模式),否则不能实现手势缩放。

              3.不用按钮,直接手势放大缩放也基本能满足需求,这里只是作为方法记录下来。 

希望能对题主解决问题有帮助。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐