Android Scroll 滑动效果 及 触摸事件处理

Android Scroll 滑动效果 及 触摸事件处理,第1张

概述AndroidScroll滑动效果触摸事件处理跟着《安卓群英传》看的,很多知识点在书上,这里就写一些小demo就好了,以后复习一、TouchEvent实现滑动——小球跟着手指走1.新建一个类继承自view,并覆写onDraw()方法packagecom.example.toucheventactivity.Bean;importandroid. AndroID Scroll 滑动效果 及 触摸事件处理

跟着《安卓群英传》看的,很多知识点在书上,这里就写一些小demo就好了,以后复习

一、touchEvent实现滑动——小球跟着手指走1.新建一个类继承自vIEw,并覆写onDraw()方法
package com.example.toucheventactivity.Bean;import androID.content.Context;import androID.graphics.Canvas;import androID.graphics.color;import androID.graphics.Paint;import androID.util.AttributeSet;import androID.vIEw.VIEw;import androID.vIEw.inputmethod.CursorAnchorInfo;import androIDx.annotation.Nullable;public class TestVIEw extends VIEw {    int x, y;    public TestVIEw(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public voID setXY(int _x, int _y) {        x = _x;        y = _y;    }    @OverrIDe    protected voID onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawcolor(color.CYAN);        Paint paint = new Paint();        paint.setcolor(color.BLACK);        paint.setAntiAlias(false);        canvas.drawCircle(x, y, 40, paint);        paint.setcolor(color.WHITE);        canvas.drawCircle(x-8,y-8,8,paint);    }}
2.把testvIEw加载到主活动上
<?xml version="1.0" enCoding="utf-8"?><androIDx.constraintlayout.Widget.ConstraintLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    xmlns:app="http://schemas.androID.com/apk/res-auto"    xmlns:tools="http://schemas.androID.com/tools"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    tools:context=".MainActivity">    <com.example.toucheventactivity.Bean.TestVIEw        androID:ID="@+ID/testvIEw"        androID:layout_wIDth="match_parent"        androID:layout_height="match_parent"        androID:text="Hello World!"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintleft_toleftOf="parent"        app:layout_constraintRight_toRightOf="parent"        app:layout_constrainttop_totopOf="parent" /></androIDx.constraintlayout.Widget.ConstraintLayout>
3.主活动java文件下编辑代码
package com.example.toucheventactivity;import androIDx.appcompat.app.AppCompatActivity;import androID.os.Bundle;import androID.vIEw.MotionEvent;import androID.vIEw.VIEw;import androID.Widget.Toast;import com.example.toucheventactivity.Bean.TestVIEw;public class MainActivity extends AppCompatActivity {    private TestVIEw mTestVIEw;    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_main);        mTestVIEw = findVIEwByID(R.ID.testvIEw);        mTestVIEw.setontouchListener(new mOntouch());    }    //处理触摸事件    private class mOntouch implements VIEw.OntouchListener {        @OverrIDe        public boolean ontouch(VIEw v, MotionEvent event) {            int x1, y1;            x1 = (int) event.getX();            y1 = (int) event.getY();            switch (event.getAction()) {                case MotionEvent.ACTION_DOWN:                    mTestVIEw.setXY(x1, y1);                    //执行刷新 *** 作                    mTestVIEw.invalIDate();                    break;                case MotionEvent.ACTION_UP:                    Toast.makeText(MainActivity.this,"您抬起了手指",Toast.LENGTH_SHORT).show();                    break;                case MotionEvent.ACTION_MOVE:                    mTestVIEw.setXY(x1,y1);                    mTestVIEw.invalIDate();                    break;                case MotionEvent.ACTION_CANCEL:                    Toast.makeText(MainActivity.this,"您取消了触碰",Toast.LENGTH_SHORT).show();                    break;            }            return true;        }    }}
4.运行效果:二、多点触控AndroID的多点触控功能需要运行在AndroID2.0版本以上支持多点触控,可以在屏幕上同时使用三个手指完成缩放、旋转或者任何使用多点触控想做的事情;多点触控和单点触控的基本原理是一直的。当手指触控屏幕是,MotionEvent对象被创建,并且被传递到前面介绍的方法中在一个手势中,可以使用getPointerID()方法获得出触碰点ID,用来在后续的触摸事件中跟踪手指。发生一系列的动作后,可以使用**findPointerIndex()**方法找到触点I当前对应的触点索引,然后使用触点索引获取触摸事件的信息。1.使用
package com.example.toucheventactivity;import androIDx.appcompat.app.AppCompatActivity;import androID.os.Bundle;import androID.util.Log;import androID.vIEw.MotionEvent;public class MultiActionActivity extends AppCompatActivity {    private static final String TAG = "MultiActionActivity";    private int pointerID;    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_multi_action);    }    @OverrIDe    public boolean ontouchEvent(MotionEvent event) {        //得出触碰点ID        pointerID = event.getPointerID(0);        //找到当前触碰点的索引        int pointerIndex = event.findPointerIndex(pointerID);        //触碰点的xy坐标        float x = event.getX(pointerIndex);        float y = event.getY(pointerIndex);        //大于一表明有多个点进行了触发        if (event.getPointerCount() > 1) {            for (int i = 0; i < event.getPointerCount(); i++) {                pointerIndex = event.findPointerIndex(i);                x = event.getX(pointerIndex);                y = event.getY(pointerIndex);                Log.d(TAG, "Mulititouch Event,The Point + " + i + ":" + "x:" + x + "," + y);            }        } else {            Log.d(TAG, "Single touch Event: ->  " + x + "," + y);        }        return true;    }    public static String actionToString(int action) {        switch (action) {            case MotionEvent.ACTION_DOWN:                return "Down";            case MotionEvent.ACTION_MOVE:                return "Move";            case MotionEvent.ACTION_CANCEL:                return "cancel";            case MotionEvent.ACTION_UP:                return "up";            case MotionEvent.ACTION_POINTER_UP:                return "Pointer Up";            case MotionEvent.ACTION_OUTSIDE:                return "OutsIDe";            case MotionEvent.ACTION_POINTER_DOWN:                return "Point Down";        }        return "";    }}
三、手势手势也是一组触摸事件的序列,由基本触摸事件的动作组成。手势可以是简单的触摸事件序列,例如单击、滑屏等,也可以是自定义更复杂的触摸事件序列。基本的手势包括单击、长按、滑动、拖动、双击、缩放 *** 作。每种手势都是用户的一种特定动作,触摸屏可以识别这些动作完成相应的功能。滑动就是手指在屏幕上拖动一个物体,快速地朝一个方向移动,然后抬起。AndroID提供了GestureDetector类检测的一些常见手势,其中的方法包括onDown()、 onLongPress()和onFling()等。另外,使用scaleGestureDetector类来实现缩放手势。当初始化GestureDetector对象时,需要传入一个实现了OnGestureListener接口的参数,当一个特定的手势被识别时,就会执行OnGestureListener中的各种手势的处理方法。为了使GestureDetector对象能够接收触摸事件,需要覆盖VIEw或Activity的ontouchEvent()方法,并将所有的触摸事件传递到GestureDetector对象中。如果只想处理部分手势,可以继承SimpleOnGestureListener。缩放手势有两种 *** 作:一种是两个手指同时触摸屏幕,向相互远离的方向移动,然后同时离开屏幕,这是放大 *** 作;另一种是两个手指同时触摸屏幕,向相互靠近的方向移动,然后同时离开屏幕,这是缩小 *** 作。1.实例:缩放一个图片
<?xml version="1.0" enCoding="utf-8"?><androIDx.constraintlayout.Widget.ConstraintLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    xmlns:app="http://schemas.androID.com/apk/res-auto"    xmlns:tools="http://schemas.androID.com/tools"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    tools:context=".MainActivity"    androID:background="#27B1B1">    <com.example.toucheventactivity.Image.ScaleImageVIEw        androID:src="@drawable/ic_launcher_foreground"        androID:layout_wIDth="match_parent"        androID:layout_height="match_parent"        androID:scaleType="matrix"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintleft_toleftOf="parent"        app:layout_constraintRight_toRightOf="parent"        app:layout_constrainttop_totopOf="parent" /></androIDx.constraintlayout.Widget.ConstraintLayout>

new一个类继承自AppCompatimageVIEw,里面用来处理手势 *** 作的主要逻辑,注释很详细了可以看着注释回忆。

package com.example.toucheventactivity.Image;import androID.content.Context;import androID.graphics.Matrix;import androID.graphics.RectF;import androID.graphics.drawable.Drawable;import androID.os.Build;import androID.util.AttributeSet;import androID.vIEw.MotionEvent;import androID.vIEw.ScaleGestureDetector;import androID.vIEw.VIEw;import androIDx.annotation.NonNull;import androIDx.annotation.Nullable;import androIDx.annotation.RequiresAPI;import androIDx.appcompat.Widget.AppCompatimageVIEw;@RequiresAPI(API = Build.VERSION_CODES.M)public class ScaleImageVIEw extends AppCompatimageVIEw implements ScaleGestureDetector.OnScaleGestureListener, VIEw.OntouchListener {    ScaleGestureDetector mScaleGestureDetector;    Matrix mScaleMatrix = new Matrix();    //当前的缩放度    float initScale = 1.0f;    //最大的缩放是6倍    static final float SCALE_MAX = 6.0f;    float[] matrixValues = new float[9];    public ScaleImageVIEw(@NonNull @org.jetbrains.annotations.NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {        super(context, attrs);        mScaleGestureDetector = new ScaleGestureDetector(context, this);        this.setontouchListener(this);    }    @OverrIDe    public boolean onScale(ScaleGestureDetector detector) {        float scale = getScale();        //检测到基于原来的缩放还有一个新的缩放尺度        float scaleFactor = detector.getScaleFactor();        //不能比最大的缩放还要大,比最小的还要小        if ((scale < SCALE_MAX && scaleFactor > 1.0f) || (scale > initScale && scaleFactor < 1.0f)) {            if ((scaleFactor * scale < initScale)) {                //放大倍数是初始缩放和当前缩放的一个比值                scaleFactor = initScale / scale;            }            if (scale * scaleFactor > SCALE_MAX) {                scaleFactor = SCALE_MAX / scale;            }        }//        mScaleMatrix.postscale(scaleFactor,scaleFactor,getWIDth()/2,getHeight()/2);        //以手势聚焦点为中心点进行缩放        mScaleMatrix.postscale(scaleFactor, scaleFactor, detector.getFocusX() / 2, detector.getFocusY() / 2);        //检查一下边界,是否有白边之类的        checkborderAndCenterWhenScale();        //保存图片的matrix        setimageMatrix(mScaleMatrix);        return true;    }    private voID checkborderAndCenterWhenScale() {        //得到当前图片的绘制区域        RectF rectF = getMatrixRecF();        //移动的空间        float deltaX = 0;        float deltaY = 0;        int wIDth = getWIDth();        int height = getHeight();        if (rectF.wIDth() >= wIDth) {            if (rectF.left > 0) {                deltaX = - rectF.left;            }            if ((rectF.right < wIDth)) {                deltaX = wIDth - rectF.right;            }        }        if (rectF.height() >= height) {            //说明图片与顶部有空白区域,需要向上调整            if (rectF.top > 0) {                deltaY = - rectF.top;            }            //说明与底部有空白,需要向下调整            if (rectF.bottom < height) {                deltaY = height - rectF.bottom;            }        }        //移动的具体方法        if (rectF.wIDth()<wIDth) {            deltaX = wIDth*0.5f - rectF.right+0.5f*rectF.wIDth();        }        if(rectF.height()<height){            deltaY = height*0.5f-rectF.bottom+0.5f*rectF.height();        }        mScaleMatrix.postTranslate(deltaX,deltaY);    }    private float getScale() {        mScaleMatrix.getValues(matrixValues);        return matrixValues[Matrix.MSCALE_X];    }    //得到当前绘图区域的边界    private RectF getMatrixRecF() {        Matrix matrix = mScaleMatrix;        RectF rectF = new RectF();        //开始绘制        Drawable d = getDrawable();        //如果不为空,则开始绘制        if (d != null) {            rectF.set(0, 0, d.getIntrinsicWIDth(), d.getIntrinsicHeight());        }        return rectF;    }    @OverrIDe    public boolean onScaleBegin(ScaleGestureDetector detector) {        return true;    }    @OverrIDe    public voID onScaleEnd(ScaleGestureDetector detector) {    }    @OverrIDe    public boolean ontouch(VIEw v, MotionEvent event) {        mScaleGestureDetector.ontouchEvent(event);        return true;    }}
public class MainActivity extends AppCompatActivity {    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_main);    }}
四、拖放 *** 作AndroID应用程序在处理拖放 *** 作时,可以通过实现VIEw.OnDragListener接口,创建拖动事件监听器;然后通过VIEw类提供的setonDragListener()方法,为VIEw对象设置一个拖动事件监听器对象。每个VIEw对象都可以有一个onDragEvent()回调方法。应用程序通过调用VIEw.OnDragListener的startDrag()方法告诉系统开始一个拖动,也就是告诉系统可以开始发送拖动事件了。一旦应用程序调用startDrag()方法,剩下的过程就是使用系统发送给布局中的视图对象的事件。拖放过程的四个基本步骤或状态: 开始继续释放终止 拖放事件: 用户界面的视图对象通过实现VIEw.OnDragListener接口的拖动事件监听器,或通过它自身的onDragEvent(DragEvent)回调方法来接收拖动事件。当系统回调这个方法或监听器时,会传递给它们一个拖动事件的对象。在AndroID系统中,使用DragEvent类来描述拖动事件。 1,设计拖动 *** 作:

开始拖动:

用户用一个拖动的手势开始一个拖动,通常是一个在视图对象上的长按动作。作为回应,需要做下面两件事情。(1)为要移动的数据创建一个clipData和ClipData.Iltem对象。(2)创建拖动阴影。

响应拖动开始事件:

在拖动过程中,系统将拖动事件传递给当前布局中的视图对象的拖动事件监听器。监听器应该调用getAction()方法获取 *** 作类型。在一个拖动开始时,该方法返回ACTION_DRAG_STARTED。

当ACTION_DRAG_STARTED事件发生时,监听器需要进行下面的处理:

(1)调用getClipDescription()方法获取ClipDescription。使用在ClipDescription 中的MIME类型的方法查看监听器是否接收被拖动的数据。如果拖放 *** 作没有数据移动,这个步骤就不是必需的。

(2)如果监听器可以接收一个拖动事件,它必须返回true。

在拖动过程中处理事件:

在拖动过程中,当监听器对ACTION_DRAG_STARTED拖动事件的返回值为true时,监听器继续接收后续的拖动事件。在拖动过程中,getAction()返回的事件类型包括三个: ACTION_DRAG_ENTERED ACTION_DRAG_LOCATION ACTION_DRAG_EXITED

响应释放动作:

当用户在某个视图上释放拖动阴影时,该视图会预先报告是否可以接收被拖动的内容,系统会将拖动事件分发给具有ACTION_DROP *** 作类型的视图。监听器在事件处理时,需要做两件事。 (1)调用getClipData()方法获取最初在startDrag()方法中应用的clipData对象,并存储。如果拖放 *** 作没有数据的移动,就不必进行该 *** 作。(2)如果释放动作已顺利完成,监听器应返回true;如果没有完成,则返回false。这个被返回的值成为ACTION_DRAG_ENDED事件中getResult()方法的返回值。 2.实现拖放 *** 作的步骤:实现拖放 *** 作的步骤共有六步,包括创建应用程序可以根据实际的情况册减步骤: 1.定义XML绘制图片;2.定义布局等资源文件;3.创建或者打开Activity,获取定义的视图对象;4.定义或实现touchListener;5.定义或实现DragListener;6.将监听器注册到视图对象。 3.实例:图片跟着手指长按进行拖动,拖动到屏幕下方时颜色改变并且显示坐标
<?xml version="1.0" enCoding="utf-8"?><relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    xmlns:app="http://schemas.androID.com/apk/res-auto"    xmlns:tools="http://schemas.androID.com/tools"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    tools:context=".MainActivity2"    androID:ID="@+ID/topContainer">    <ImageVIEw        androID:ID="@+ID/img"        androID:src="@drawable/ic_androID_black_24dp"        androID:layout_wIDth="wrap_content"        androID:layout_height="wrap_content"/>    <linearLayout        androID:ID="@+ID/container"        androID:layout_wIDth="match_parent"        androID:layout_height="100dp"        androID:layout_alignParentBottom="true"        androID:orIEntation="vertical"        androID:background="#ccc">        <TextVIEw            androID:ID="@+ID/Title"            androID:textcolor="#f00"            androID:textSize="18sp"            androID:layout_wIDth="match_parent"            androID:layout_height="wrap_content"/>    </linearLayout></relativeLayout>
package com.example.toucheventactivity;import androIDx.annotation.RequiresAPI;import androIDx.appcompat.app.AppCompatActivity;import androID.content.ClipData;import androID.content.ClipDescription;import androID.graphics.color;import androID.os.Build;import androID.os.Bundle;import androID.vIEw.DragEvent;import androID.vIEw.VIEw;import androID.Widget.ImageVIEw;import androID.Widget.linearLayout;import androID.Widget.relativeLayout;import androID.Widget.TextVIEw;public class MainActivity2 extends AppCompatActivity {    static final String IMAGEVIEW_TAG = "已经拖到了目标区域";    ImageVIEw imageVIEw;    linearLayout mContainer;    relativeLayout mtopContainer;    TextVIEw mTitle;    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_main2);        imageVIEw = findVIEwByID(R.ID.img);        imageVIEw.setTag(IMAGEVIEW_TAG);        mContainer = findVIEwByID(R.ID.container);        mTitle = findVIEwByID(R.ID.Title);        mtopContainer = findVIEwByID(R.ID.topContainer);        imageVIEw.setonLongClickListener(new VIEw.OnLongClickListener() {            @RequiresAPI(API = Build.VERSION_CODES.N)            @OverrIDe            public boolean onLongClick(VIEw v) {                //设置一个剪切板                ClipData.Item item = new ClipData.Item((String) v.getTag());                //设置剪切板里面的内容                ClipData data = new ClipData(IMAGEVIEW_TAG, new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}, item);                //开始拖动时,传入数据,并设置一个影子                /**                 * new VIEw.DragShadowBuilder(v)                 * 就是在给该视图设置一个阴影                 */                v.startDragAndDrop(data, new VIEw.DragShadowBuilder(v), null, 0);                return true;            }        });        //当拖放的对象拖到了mtopContainer之后,就会执行该方法        mtopContainer.setonDragListener(new VIEw.OnDragListener() {            @OverrIDe            public boolean onDrag(VIEw v, DragEvent event) {                int action = event.getAction();                switch (action) {                    //开始拖动的时候                    case DragEvent.ACTION_DRAG_STARTED:                        return true;                    //进入的时候                    case DragEvent.ACTION_DRAG_ENTERED:                        return true;                    //定位的时候                    case DragEvent.ACTION_DRAG_LOCATION:                        return true;                    //离开的时候                    case DragEvent.ACTION_DRAG_EXITED:                        mTitle.setText("");                        return true;                    //释放的时候                    case DragEvent.ACTION_DROP:                        imageVIEw.setX(event.getX() - imageVIEw.getWIDth() / 2);                        imageVIEw.setY(event.getY() - imageVIEw.getHeight() / 2);                        return true;                    //当你拖放结束的时候                    case DragEvent.ACTION_DRAG_ENDED:                        return true;                }                return false;            }        });        mContainer.setonDragListener(new VIEw.OnDragListener() {            @OverrIDe            public boolean onDrag(VIEw v, DragEvent event) {                int action = event.getAction();                switch (action) {                    //开始拖动的时候                    case DragEvent.ACTION_DRAG_STARTED:                        if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)){                            return true;                        }                        return false;                    //进入的时候                    case DragEvent.ACTION_DRAG_ENTERED:                        mContainer.setBackgroundcolor(color.YELLOW);                        return true;                    //定位的时候                    case DragEvent.ACTION_DRAG_LOCATION:                        return true;                    //离开的时候                    case DragEvent.ACTION_DRAG_EXITED:                        mContainer.setBackgroundcolor(color.BLUE);                        return true;                    //释放的时候                    case DragEvent.ACTION_DROP:                        //释放的时候,将坐标显示到TextVIEw上面                        ClipData.Item item = event.getClipData().getItemAt(0);                        String dragData = item.getText().toString();                        mTitle.setText(dragData+"  "+ event.getX()+":"+event.getY());                        return true;                    //当你拖放结束的时候                    case DragEvent.ACTION_DRAG_ENDED:                        return true;                }                return false;            }        });    }}

注释很清楚了,自己看注释就好了。

@H_429_301@

总结

以上是内存溢出为你收集整理的Android Scroll 滑动效果 及 触摸事件处理全部内容,希望文章能够帮你解决Android Scroll 滑动效果 及 触摸事件处理所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1080701.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-27
下一篇2022-05-27

发表评论

登录后才能评论

评论列表(0条)

    保存