自定义viewpager,实现图片多指触控,双击,放大或缩小,和viewpager的冲突

本文介绍了如何自定义ViewPager,实现图片的多指触控缩放以及双击图片放大或缩小的功能。同时,讨论了在实现过程中可能遇到的与ViewPager原有滑动冲突的问题,提供了解决方案。
摘要由CSDN通过智能技术生成

//在main中的布局

   
   

    
    
    
   


   
   

//在ViewPager的item中的布局

   
   

    
    
    
   


   
   

//自定义ImageView
import android.R.bool;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
import android.view.View.OnTouchListener;

public class ZoomImageView extends ImageView implements OnGlobalLayoutListener, OnScaleGestureListener,OnTouchListener{

	private boolean mOnce = false;
	//初始化缩放的值
	private float mInitScale;
	//双击放大值到达的值
	private float mMidScale;
	//放大的最大值
	private float mMaxScale;
	private Matrix mScaleMatrix;
	//捕获用户多指触控时缩放的比例‘
	private ScaleGestureDetector mScaleGestureDetector;
	
	//====================图片自由移动
	private int mLastPointerCount;//记录上一次多点触控的数量
	private float mLastX;
	private float mLastY;//记录最后一次x,y的坐标
	private int mTouchSlop;//获取系统的值
	private boolean isCanDrag;
	//判断 控件左右,上下是否超出
	private  boolean isCheckLeftAndRight;
	private  boolean isCheckTopAndBottom;
	
	//==========双击放大与缩小
	private GestureDetector mGestureDetector;
	private boolean  isAutoScale;
	public ZoomImageView(Context context) {
		super(context); 
	}
	public ZoomImageView(Context context, AttributeSet attrs) {
		super(context, attrs); 
		mScaleMatrix = new Matrix();
		mScaleGestureDetector = new ScaleGestureDetector(context, this);
	    setOnTouchListener(this);
	    //图片自由移动时,获取的系统的值
	    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
	    mGestureDetector = new GestureDetector(context, 
	    		new GestureDetector.SimpleOnGestureListener(){
	    	public boolean onDoubleTap(MotionEvent e) {
	    		//如果用户已经点击过了,并且此时正在放大或者缩小,就不让点击
	    		if(isAutoScale)
					return true;
	    		
	    		//当前点击的x,y的坐标,已点击的点为屏幕的中心点
	    		float x = e.getX();
	    		float y = e.getY();
	    		
	    		if(getScale()
   
   
    
    mTargetScale){//缩小
				tmpScale = SMALL;
			}
			
		}

		public void run() {
			//进行缩放
			mScaleMatrix.postScale(tmpScale, tmpScale, x, y);
			checkBorderAndCenterWhenScale();
			setImageMatrix(mScaleMatrix);
			
			float currentScale = getScale();
			
			if(tmpScale >1.0f&&currentScale
    
    
     
     mTargetScale){
				//每16毫秒执行一次这个方法
				postDelayed(this, 50);
			}else{//设置为我们的目标值
				float scale = mTargetScale/currentScale;
				mScaleMatrix.postScale(scale, scale, x, y);
				checkBorderAndCenterWhenScale();
				setImageMatrix(mScaleMatrix);
				isAutoScale = false;
			}
		}
		
	}

	//全局布局完成之后,会执行这样一个方法
	//获得ImagerView加载完成的图片
	public void onGlobalLayout() {
		//保证只会进行一次的比较
		if(!mOnce){
			//获得控件的宽高
			//一般控件的宽高,就是屏幕的宽高
			int wight = getWidth();
			int height = getHeight();
			//得到我们的图片,以及宽和高
			Drawable d = getDrawable();
			if(d == null){
				return ;
			}
			int dw = d.getIntrinsicWidth();
			int dh = d.getIntrinsicHeight();
			
			//设置一个缩放值
			float scale = 1.0f;
			
			//如果图片的宽度大于控件的宽度,高度小于控件的宽高,那么将其缩放
			if(dw>wight && dh
     
     
      
      height){
				scale = height*1.0f/dh;
			}
			
			//宽高均小于控件宽高,宽高均大于控件宽高,将其缩放或扩大
			if((dw>wight && dh>height)||(dw
      
      
       
       1.0f)||(scale>mInitScale&&scaleFactor<1.0f)){
			//当你想缩的特别小时,我们就将mInitScale设置给你
			if(scale*scaleFactor < mInitScale){
				scaleFactor = mInitScale/scale;
			}
			//当你想放的特别大时,我们就将mMaxScale设置给你
			if(scale*scaleFactor > mMaxScale){
				scaleFactor = mMaxScale/scale;
			}
			
			//缩放中心点
			mScaleMatrix.postScale(scaleFactor, scaleFactor,detector.getFocusX(),detector.getFocusY());
			//在缩放的时候,进行边界的控制,以及我们的位置的控制
			checkBorderAndCenterWhenScale();
			setImageMatrix(mScaleMatrix);
			 
		}
		return true;
	}
	
	public boolean onScaleBegin(ScaleGestureDetector detector) {
		//必须将返回值改为true;
		return true;
	}

	public void onScaleEnd(ScaleGestureDetector detector) {
	}
   
	//RectF是一个矩形,里边所有的值是浮点型
	//获得图片放大缩小以后的宽和高,以及left,right,top,buttom
	private RectF getMatrixRectF(){
		Matrix matrix = mScaleMatrix;
		RectF rectF = new RectF();
		Drawable d = getDrawable();
		if(d != null){
			rectF.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
		    matrix.mapRect(rectF);
		}
		return rectF;
	}
	
	//在缩放的时候,进行边界的控制,以及我们的位置的控制
	private void checkBorderAndCenterWhenScale() {
		//调用 getMatrixRectF()获得RectF
		RectF rect = getMatrixRectF();
		
		//左边和右边的差值
		float deltaX = 0;
		float deltaY = 0;
		
		//宽高
		int width = getWidth();
		int height = getHeight();
		//缩放时,进行边界测试,放置出现白边
		//rect.width()是通过放大缩小之后的图片的宽度
		//水平方向上的控制
		if(rect.width() >= width){
			 if(rect.left>0){
				 deltaX = -rect.left;
			 }
			 if(rect.right
       
       
         =height){ if(rect.top>0){ deltaY = -rect.top; } if(rect.bottom 
        
          getWidth()+0.01||rectF1.height()>getHeight()+0.01){ getParent().requestDisallowInterceptTouchEvent(true); } case MotionEvent.ACTION_MOVE: if(rectF1.width()>getWidth()+0.01||rectF1.height()>getHeight()+0.01){ getParent().requestDisallowInterceptTouchEvent(true); } //记录x,y的偏移量(这次的中心点坐标减去上次中心点的坐标) float dx = x-mLastX; float dy = y-mLastY; //在手指触控的个数发生变化,但是又想移动图片时,去判断,移动的偏移量是否足以触发移动 if(!isCanDrag){ isCanDrag = isMoveAction(dx, dy); } //移动过程的一个操作 if(isCanDrag){ RectF rectF = getMatrixRectF(); if(getDrawable() != null){ //每次都去检测图片 isCheckLeftAndRight = isCheckTopAndBottom = true; //如果宽度小于控件宽度 ,不允许横向移动(说明此图片横向上已完全显示) if(rectF.width() 
         
           0 && isCheckTopAndBottom){ deltaY = -rectF.top; } //底部不能出现 白边 if(rectF.bottom 
          
            0 && isCheckLeftAndRight){ deltaX = -rectF.left; } //右边不能出现白边 if(rectF.right 
           
             mTouchSlop; } } //在mainAcitity中 import com.example.view.ZoomImageView; import android.os.Bundle; import android.app.Activity; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.ZoomButton; public class MainActivity extends Activity { private ViewPager mViewPager; private int [] mImgs = new int[]{R.drawable.af,R.drawable.ae,R.drawable.ah}; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mViewPager = (ViewPager) findViewById(R.id.view_pager); mViewPager.setAdapter(new PagerAdapter() { public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } public int getCount() { return mImgs.length; } public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View)object); } public Object instantiateItem(ViewGroup container, int position) { View view = View.inflate(MainActivity.this, R.layout.vp, null); ZoomImageView imageView = (ZoomImageView) view.findViewById(R.id.zv); imageView.setImageResource(mImgs[position]); container.addView(view); return view; } }); } } 
            
           
          
         
       
      
      
     
     
    
    
   
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值