安卓点击小图上面变换大图图片后根据触摸变换

他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)安卓触摸事件的分发,处理和消费,以及实现图片的拖动效果 - JsAko飞得更远 - 博客园
随笔 - 33, 文章 - 0, 评论 - 0, 引用 - 0
Touch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。
View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。
ViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。
而dispatchTouchEvent是用来分发触摸事件的,onTouchEvent是用来处理触摸事件的()
第一步、触摸事件的产生:
触摸事件由用户触摸屏幕,系统会生成一个MotionEvent触摸事件对象,里面封装了此次动作的所用信息,如时间,位置坐标等。
然后系统会将当前这个触摸事件交给当前的Activity来处理。
第二步、触摸事件的分发与处理:
1、系统将触摸事件交给Activity处理后,会调用Activity的dispatchTouchEvent方法进行事件的分发,Activity首先会找到活动对应的布局中的
父ViewGroup,将触摸事件交给他处理。
2、然后这个ViewGroup又会调用自身的dispatchTouchEvent方法对事件进行分发:
这里又分为两种情况:
第一种是ViewGroup分发事件找到了对应的子View进行处理。
交给它的子孩子View来处理,子孩子View得到事件后,也会调用自身的dispatchTouchEvent方法,但是View的分发则是调用View自身的onTouchEvent或者View设置的
OnTouchListener的onTouch方法对事件进行处理(这里值得一提的是,onTouch方法的优先级是比onTouchEvent方法的优先级高,即先执行onTouch方法)。
在onTouchEvent和onTouch方法中,都需要返回一个布尔类型的值,如果返回true,则说明触摸事件已经消费,不在往下传递,有拦触摸截掉事件的意义,其他子
View就不能响应到这个触摸事件,如果返回false,则说明触摸事件没有被消费,需要传递给其他子View处理。如果所有的子View都不消费这个触摸事件
,最后这个触摸事件就会交由Activity的onTouchEvent处理。
一个完整触摸事件由down、move、up组成。
这里值得我注意的是:Activity分发事件是根据该View是否消费了动作为Down的触摸事件,如果没有消费,则不会向它分发动作为UP和MOVE的触摸事件。
第二种是ViewGroup分发事件没找到对应的子View进行处理。
这时事件就由ViewGroup自己处理,它会调用自身的onTouchEvent返回false,说明事件没有找到消费者,触摸事件没有被消费,move,up 动作不需要再往下分发了,
直接调用当前Activity的onTouchEvent(ev)方法处理。
只有View消费了动作为Down的触摸事件,这个View才能响应其他两个动作的触摸事件。
说完安卓事件的分发,接下来我们就来说说图片拖动效果的实现。
第一步、为ImageView设置一个OnTouchListener,并实现其onTouch方法
第二步、拖动逻辑的实现:
1、手指按到imageView上会有一个初始位置(startX,startY)
2、手指在屏幕上移动,移动到一个新的位置(nowX,nowY)
3、计算手指在屏幕的偏移量
dx=nowX-startX
dy=nowY-startY
4、重新计算图片的位置,并控制范围,使图片不会超出边框
int left=miv_show.getLeft()+
int top=miv_show.getTop()+
int right=miv_show.getRight()+
int buttom=miv_show.getBottom()+
            if(left&=0){
if(top&=0){
if(right&=mRight){
left+=-(right-mRight);
if(buttom&=mButtom){
top+=-(buttom-mButtom);
5、通过调用imageView.layout(left,top,right,bottom)立即更新imageView的位置
(left指的是图片左上角的x坐标,top指的是图片左上角的y坐标,right指的是右下角的x坐标,bottom知道是图片右下角的y坐标)
6、重新初始化手指的开始位置(startX=nowX,startY=nowY)
7、当手指离开图片的时候记录当前图片的位置,在下次imageView加载完成后回显。
这里问题就来了,imageView什么时候会加载完成呢?当活动创建调用onCreate方法的时候
imageView是还没有加载完成的,如果在onCreate方法中调用imageView.layout方法是不起作用的
,故我们要设置一个监听,当图片加载完成后回调该监听的方法,在这个方法里面调用layout回显图片的位置,
代码如下:
miv_show.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
System.out.println("view加载完成");
int lastLeft=sp.getInt("lastLeft", 0);
int lastTop=sp.getInt("lastTop", 0);
int lastRight=sp.getInt("lastRight", 0);
int lastButtom=sp.getInt("lastButtom", 0);
if(!(lastLeft==0&&lastTop==0&&lastRight==0&&lastButtom==0)){
//说明保存了位置
miv_show.layout(lastLeft, lastTop, lastRight, lastButtom);
代码实现如下:
miv_show.setOnTouchListener(new OnTouchListener() {
private int startX;
private int startY;
public boolean onTouch(View v, MotionEvent event){
int mRight=rl.getRight();
int mButtom=rl.getBottom();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
startX=(int) event.getRawX();
startY=(int) event.getRawY();
case MotionEvent.ACTION_MOVE:
int nowX=(int) event.getRawX();
int nowY=(int) event.getRawY();
int dx=nowX-startX;
int dy=nowY-startY;
int left=miv_show.getLeft()+
int top=miv_show.getTop()+
int right=miv_show.getRight()+
int buttom=miv_show.getBottom()+
if(left&=0){
if(top&=0){
if(right&=mRight){
left+=-(right-mRight);
if(buttom&=mButtom){
top+=-(buttom-mButtom);
miv_show.layout(left,top, right, buttom);
startX=nowX;
startY=nowY;
case MotionEvent.ACTION_UP:
int lastLeft=miv_show.getLeft();
int lastTop=miv_show.getTop();
int lastRight=miv_show.getRight();
int lastButtom=miv_show.getBottom();
Editor editor=sp.edit();
editor.putInt("lastLeft", lastLeft);
editor.putInt("lastTop", lastTop);
editor.putInt("lastRight", lastRight);
editor.putInt("lastButtom", lastButtom);
editor.commit();
//返回true代表事件已经消费了,不需要再往下传递
//代表所有触摸事件都在这里被消费了,不再往下传递
return true;在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
一直想自己实现图片缩放功能
图片可以根据双指触摸位置,进行局部放大(可能描述的不准确)
我的思路是
touchstart:记录
图片的左上角坐标c1[x,y],
event.targetTouches[0]的坐标a1[x,y]
event.targetTouches[1]的坐标b1[x,y]
touchmove:记录
event.targetTouches[0]的坐标a2[x,y]
event.targetTouches[1]的坐标b2[x,y]
放大倍数 k = a2,b2间的距离/a1,b1 ;
对图片进行缩放
再求得c2的位置,对图片进行重定位,就可实现局部放大。
不过何种算法可以快速求得c2坐标呢?//我尝试了用向量去解决,但有些麻烦
求详细解答,
或者我的思路有问题?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
双指缩放的本质是什么?以触摸的两点的连线的中心点为变换中心点,做缩放变换。
常见的解法可以采用变换矩阵,既用变换矩阵(transform matrix)点乘(x, y, 1)T,得到新坐标(x', y')。
变换矩阵即上图中蓝色的部分。
本问题中的transform matrix即下面三个矩阵按顺序点乘:
坐标系变换矩阵(位移向量:旧原点向新原点)
还原坐标系变化(位移向量:新原点向旧原点)
这里我们用到了两种矩阵:
第1、第3步用到了translate matrix
第2步用到了scaling matrix
假设触摸的两点的连线的中心点M的坐标为(Xc, Yc),放大倍率为k,则变换矩阵为:
以此算得新(x', y'):
好啦,我知道大家这么聪明,肉眼就能看出这个公式。当问题更加复杂(三维?加入两指旋转?)的时候,也是可以用同样的方法来庖丁解牛的。
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。& Android游戏开发16:触摸屏手势识别编程 实现手势操作切换图片的实例
Android游戏开发16:触摸屏手势识别编程 实现手势操作切换图片的实例
&&&&&&&对于Android 的手势不光在软件中会经常用到,比如浏览器中的翻页,滚动页面等等;当然其实在我们开发Android游戏的时候加上了Android手势操作更会让游戏增加一个亮点,比如一般的CAG、PUZ等类型的游戏选择关卡、简单背景的移动等,都可以使用手势来操作即可,类似前段时间很火的《愤怒的小鸟》,小鸟这个游戏确实不错,我所看到的唯一的亮点是这款游戏的创意!说实话,现在的游戏没有做不出来的只有想不出来的好创意。回到话题来,那么下面我们来了解下什么是Android 手势!&&&&&& 手势识别概述&&&&&&&所谓,类似跳舞机、EZdancer等这些利用不同动作和音符让人手舞足蹈一样,那么Android这里的手势只是让我们在游戏和软件中的操作有了更多的花样和玩法,根据玩家接触屏幕时间的长短,在屏幕上滑动的距离,按下抬起的时间等进行了包装,其实就是Android 对触屏处理做了包装和处理。&&&&&& 那么在Android中其实有两种手势识别技术。一种是触摸屏手势识别,另一种是输入法手势识别。两者比较起来第二种比较灵活,可以自定义手势,比较high!那么这一节我们先来介绍第一种手势识别:触摸屏手势识别。在下篇博文中我会给童鞋们讲解输入法手势识别!&&&&&& 手势识别实例&&&&&& 先把两张截图放上来吧:&&&&&& OK,先上代码:&&&&&& MySurfaceView.java
package&com. &&
import&java.util.V &&
import&android.content.C &&
import&android.graphics.B &&
import&android.graphics.BitmapF &&
import&android.graphics.C &&
import&android.graphics.C &&
import&android.graphics.P &&
import&android.util.L &&
import&android.view.GestureD &&
import&android.view.MotionE &&
import&android.view.SurfaceH &&
import&android.view.SurfaceV &&
import&android.view.V &&
import&android.view.GestureDetector.OnGestureL &&
import&android.view.SurfaceHolder.C &&
import&android.view.View.OnTouchL &&
public&class&MySurfaceViewAnimation&extends&SurfaceView&implements&Callback, &&
&&&&&&&&Runnable,&OnGestureListener,&OnTouchListener&{ &&
&&&&private&Thread&th&=&new&Thread(this); &&
&&&&private&SurfaceHolder& &&
&&&&private&Canvas& &&
&&&&private&Paint& &&
&&&&private&Bitmap& &&
&&&&private&GestureDetector& &&
&&&&private&int&bmp_x,&bmp_y; &&
&&&&private&boolean&isChageP &&
&&&&private&Vector&String&&v_&&
&&&&public&MySurfaceViewAnimation(Context&context)&{ &&
&&&&&&&&super(context); &&
&&&&&&&&v_str&=&new&Vector&String&(); &&
&&&&&&&&this.setKeepScreenOn(true); &&
&&&&&&&&bmp&=&BitmapFactory.decodeResource(getResources(), &&
&&&&&&&&&&&&&&&&R.drawable.himi_dream); &&
&&&&&&&&sfh&=&this.getHolder(); &&
&&&&&&&&sfh.addCallback(this); &&
&&&&&&&&paint&=&new&Paint(); &&
&&&&&&&&paint.setAntiAlias(true); &&
&&&&&&&&this.setLongClickable(true); &&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&this.setOnTouchListener(this);&&
&&&&&&&&gd&=&new&GestureDetector(this); &&
&&&&&&&&gd.setIsLongpressEnabled(true); &&
&&&&public&void&surfaceCreated(SurfaceHolder&holder)&{ &&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&bmp_x&=&(getWidth()&-&bmp.getWidth())&&&&2; &&
&&&&&&&&bmp_y&=&(getHeight()&-&bmp.getHeight())&&&&2; &&
&&&&&&&&th.start(); &&
&&&&public&void&draw()&{ &&
&&&&&&&&try&{ &&
&&&&&&&&&&&&canvas&=&sfh.lockCanvas(); &&
&&&&&&&&&&&&if&(canvas&!=&null)&{ &&
&&&&&&&&&&&&&&&&canvas.drawColor(Color.WHITE);&&
&&&&&&&&&&&&&&&&canvas.drawBitmap(bmp,&bmp_x,&bmp_y,&paint); &&
&&&&&&&&&&&&&&&&paint.setTextSize(20);&&
&&&&&&&&&&&&&&&&paint.setColor(Color.WHITE); &&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&canvas.drawRect(50,&30,&175,120,&paint); &&
&&&&&&&&&&&&&&&&paint.setColor(Color.RED);&&
&&&&&&&&&&&&&&&&if&(v_str&!=&null)&{ &&
&&&&&&&&&&&&&&&&&&&&for&(int&i&=&0;&i&&&v_str.size();&i++)&{ &&
&&&&&&&&&&&&&&&&&&&&&&&&canvas.drawText(v_str.elementAt(i),&50,&50&+&i&*&30, &&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&paint); &&
&&&&&&&&&&&&&&&&&&&&} &&
&&&&&&&&&&&&&&&&} &&
&&&&&&&&&&&&} &&
&&&&&&&&}&catch&(Exception&e)&{ &&
&&&&&&&&&&&&Log.v(&Himi&,&&draw&is&Error!&); &&
&&&&&&&&}&finally&{ &&
&&&&&&&&&&&&sfh.unlockCanvasAndPost(canvas); &&
&&&&&&&&} &&
&&&&@Override&&
&&&&public&void&run()&{ &&
&&&&&&&&&&
&&&&&&&&while&(true)&{ &&
&&&&&&&&&&&&draw(); &&
&&&&&&&&&&&&try&{ &&
&&&&&&&&&&&&&&&&Thread.sleep(100); &&
&&&&&&&&&&&&}&catch&(Exception&ex)&{ &&
&&&&&&&&&&&&} &&
&&&&&&&&} &&
&&&&public&void&surfaceChanged(SurfaceHolder&holder,&int&format,&int&width, &&
&&&&&&&&&&&&int&height)&{ &&
&&&&public&void&surfaceDestroyed(SurfaceHolder&holder)&{ &&
&&&&@Override&&
&&&&public&boolean&onTouch(View&v,&MotionEvent&event)&{&&
&&&&&&&&if&(v_str&!=&null) &&
&&&&&&&&&&&&v_str.removeAllElements(); &&
&&&&&&&&return&gd.onTouchEvent(event);&&
&&&&@Override&&
&&&&public&boolean&onDown(MotionEvent&e)&{ &&
&&&&&&&&&&
&&&&&&&&v_str.add(&onDown&); &&
&&&&&&&&return&false; &&
&&&&@Override&&
&&&&public&void&onShowPress(MotionEvent&e)&{ &&
&&&&&&&&v_str.add(&onShowPress&); &&
&&&&@Override&&
&&&&public&void&onLongPress(MotionEvent&e)&{ &&
&&&&&&&&v_str.add(&onLongPress&); &&
&&&&@Override&&
&&&&public&boolean&onScroll(MotionEvent&e1,&MotionEvent&e2,&float&distanceX, &&
&&&&&&&&&&&&float&distanceY)&{ &&
&&&&&&&&v_str.add(&onScroll&); &&
&&&&&&&&return&false; &&
&&&&@Override&&
&&&&public&boolean&onFling(MotionEvent&e1,&MotionEvent&e2,&float&velocityX, &&
&&&&&&&&&&&&float&velocityY)&{ &&
&&&&&&&&v_str.add(&onFling&); &&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&&&
&&&&&&&&if&(isChagePage) &&
&&&&&&&&&&&&bmp&=&BitmapFactory.decodeResource(getResources(), &&
&&&&&&&&&&&&&&&&&&&&R.drawable.himi_dream); &&
&&&&&&&&else&&
&&&&&&&&&&&&bmp&=&BitmapFactory.decodeResource(getResources(), &&
&&&&&&&&&&&&&&&&&&&&R.drawable.himi_warm); &&
&&&&&&&&isChagePage&=&!isChageP &&
&&&&&&&&return&false; &&
&&&&@Override&&
&&&&public&boolean&onSingleTapUp(MotionEvent&e)&{ &&
&&&&&&&&v_str.add(&onSingleTapUp&); &&
&&&&&&&&return&false; &&
}&&&&&&&& 补充一下:代码初始化手势的时候有这么一句:gd.setIsLongpressEnabled(true);这个函数标识,如果你设置true的话就是开启了长按键,当你长时间触屏不动就能得到 onLongPress 手势,如果设置false,那么你长时间触屏不移动也得不到这个手势的支持。此函数不设置也默认设置为true。&&&&&& 备注1:&&&&&&&这里我只是给一些不太熟悉这种定义Vector方式的童鞋简单介绍一下:我们一般定义容器的时候都是直接 Vector vc =new Vector();,嗯,没错,但是这种Vector&String&的定义是种泛型定义,那么简单的说下区别,如果Vector vc =new Vector();这种方式装入Object的以后,取的时候是不是要把取出的进行强转一下类型?! 呵呵,而Vector&String&这种定义的时候就表明了这个容器我只装String类型的元素,so~取出的时候也不用再去强转了。&&&&&& 备注2:&&&&&& 通过测试发现,这里仍然响应,即使你把触屏焦点设置成setFocusableInTouchMode(false)也会调用!原因是因为我们本类的view绑定了触屏事件监听器,那么肯定会先响应备注3,然后我们备注4这里没有 return true 而是直接返给了手势监听器去监听,让监听器找合适的函数来处理用户的手势,也就是说没有标志处理完成,所以我们的重写的onTouchEvent()也会继续去处理!&&&&&& 备注5:&&&&&& 这里注释的代码我是在测试两个动作到底是哪两个,因为网上介绍Android手势帖子都疯传说:&&&&&& 第一个是MotionEvent.ACTION_DOWN,第二个是MotionEvent.ACTION_MOVE。那么第一个动作是按下好理解,是玩家刚触屏的动作,第二个是move!难道是移动的点都记录下来了??&&&&&& 其实测试结果发现:&&&&&& 第一个是MotionEvent.ACTION_DOWN,第二个是MotionEvent.ACTION_UP!&&&&&& 唉~现在网上的帖子真是各种抄袭~就不能测试下??郁闷! 既然这两个动作一个是按下一个是抬起那就很明确其意义了,我们可以根据这两个动作知道用户到底滑动的距离等等了,其距离e2.getX()-e1.getX()。&&&&&& 总结&&&&&& 1、触屏后、一直触屏不动、演变顺序:onDown-&onShowPress-&onLongPress;&&&&&& 2、触屏后、一直触屏慢移动是onScroll/快移动是onFling 、手指离开屏幕;&&&&&& 注意 :触屏后、一直触屏移动,如果手指不离开屏幕一直都是onScroll,不管你移动的速度多快,永远不会是onFling!&&&&&& Ok,手势虽然挺简单的,但是如果熟练来使用并且加入游戏中肯定让你的Game增色不少。&&&&&& 这个实例我只做了一个手势的处理,因为其他的动作都很简单就不多说了。&&&&&& 补充内容:&&&&&&&网上很多关于手势文章都说Android 对手势的支持是从SDK 1.6 (也就是 API 4)才开始的,但是我用SDK1.5模拟器也能识别!(本想测试下更低的SDK的支持效果,但是我没有SDK低于1.5版本的),所以查了Api 发现:&&&&&&&&& android.view.GestureDetector.OnGestureL&&& since api-1 ,&&&&&&&&& android.view.GestureD& since api-1 ,&&&&&&&从API来看从api-1开始就已经支持手势和手势监听器了,那么很多说api-4才支持这句话也没错!因为:android.gesture 这个类是从 api-4才开始支持的,这个类输入法手势识别中会用到。&&&&&&&结论:触摸屏手势识别是从API-1 就开始支持了。 而输入法手势识别是API-4才开始支持的!这里要搞清楚!
本文发布:
本文地址:
发布:鸡啄米
&&( 21:30:7)&&( 23:28:18)&&( 22:41:50)&&( 21:42:35)&&( 22:24:33)&&( 20:51:49)
( ⊙ o ⊙ )啊!
完全随机文章【图片】安卓的模拟器是如何把鼠标点击转成触控操作的?【androidx86吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:14,197贴子:
安卓的模拟器是如何把鼠标点击转成触控操作的?收藏
装了个安卓X86也把想玩的游戏启动了,然而那个游戏根本不识别鼠标控制。想起来原先用模拟器的时候是可以鼠标代替触控的,到底模拟器是如何办到的?能否用同样原理移植给真机的安卓X86?有没有大神可以讲讲?谢谢
Tincore Keymapper 可以把鼠标移动设为 hybird point move左键点击设为 touch hybird point然后可能要设详细设定的 touch screen那边看看解析度因为如果不一致 可能会发生按下去跟感应到的位置不一样我是直接使用 谷哥 paly上面最新的的 因为先前使用汉化版的较早版本发现移动位置方向不对基本上4.4rc3这一版开始大部分的横屏游戏都没问题了(gtx650 玩3d手游无压力 )另外 竖屏的游戏可能会有问题 一样是触控的位置和感应到的不一样 还没研究出来怎么修改设置
登录百度帐号

我要回帖

更多关于 dw鼠标点击变换图片 的文章

 

随机推荐