Android中实现滑动(上)----基础知识

Android当中的滑动效果可以有效改善之前的点击,长按等UI体验,今天就来看一看其具体的实现,下面将会分为两个部分展开介绍,第一部分介绍一下基础知识,第二部分介绍具体的几种实现方式。

1,Android中的坐标系

1.1 Android坐标系

如下图所示,Android中的坐标系是向右为X轴正方向,向下为Y轴正方向;其中(0,0)坐标对应于手机屏幕的左上角

1.2 视图坐标系

如下图所示,其中(0,0)代表父布局的左上角(嵌套同理)

2,触控事件

MotionEvent对于用户与界面的交互来说必不可少,当然随着语音识别等AI技术的成熟,这种依赖会降低,目前我们在做的机器人产品用户与机器人交互主要是通过ASR和TTS以及人脸识别等,界面更多的是展示功能。其中MotionEvent中定义了很多事件常量,主要如下:

 MotionEvent.ACTION_DOWN
 MotionEvent.ACTION_UP
 MotionEvent.ACTION_MOVE
 MotionEvent.ACTION_CANCEL
 MotionEvent.ACTION_OUTSIDE
 MotionEvent.ACTION_POINTER_DOWN
 MotionEvent.ACTION_POINTER_UP
 MotionEvent.ACTION_BUTTON_PRESS
 MotionEvent.ACTION_HOVER_ENTER 
 MotionEvent.ACTION_HOVER_EXIT
 MotionEvent.ACTION_HOVER_MOVE
 MotionEvent.ACTION_MASK
 MotionEvent.ACTION_POINTER_INDEX_MASK
 MotionEvent.ACTION_POINTER_INDEX_SHIFT
 MotionEvent.ACTION_BUTTON_RELEAS

等,我们只需要在获取控件的时候设置onTouchEvent(EventMotion event)即可根据event收到的事件类型来做业务处理

3,获取坐标

3.1 通过View

getLeft()                    //获取View的左边到其父布局左边距离

getTop()                    //获取View的上边到其父布局上边距离

getRight()                 //获取View的右到其父布局左边距离

getBottom()             //获取View的底边到其父布局上边边距离

3.2 通过MotionEvent

getX()                               //点击事件位置距离控件自身左边的距离

getY()                               //点击事件位置距离控件自身上边的距离

getRawX()                       //点击事件位置距离控件屏幕左边的距离

getRawY()                        //点击事件位置距离控件屏幕上边的距离

4,示例代码和解释

4.1 代码

MainActivity代码:

package com.hfut.operationscrollpre;

import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

/**
 * @author why
 * @date 2018-8-18 15:15:13
 */
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    Button button;
    LinearLayout linearLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.test_button);
        linearLayout = findViewById(R.id.test_layout);

//        ActionBar actionBar=getSupportActionBar();
//        if(actionBar!=null){
//            actionBar.hide();
//        }

        button.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_DOWN");
                        Log.d("按钮:点击坐标(相对控件本身):", "onTouch: x," + event.getX() + ";y," + event.getY());
                        Log.d("按钮:点击坐标(相对上层布局):", "onTouch: Left," + v.getLeft() + ";Top," + v.getTop() + ";Right," + v.getRight()
                                + ";Bottom," + v.getBottom());
                        Log.d("按钮:点击坐标(相对整个屏幕):", "onTouch: X," + event.getRawX() + ";Y," + event.getRawY());
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_UP");
                        Log.d("按钮:点击坐标(相对控件本身):", "onTouch: x," + event.getX() + ";y," + event.getY());
                        Log.d("按钮:点击坐标(相对上层布局):", "onTouch: Left," + v.getLeft() + ";Top," + v.getTop() + ";Right," + v.getRight()
                                + ";Bottom," + v.getBottom());
                        Log.d("按钮:点击坐标(相对整个屏幕):", "onTouch: X," + event.getRawX() + ";Y," + event.getRawY());
                        break;
                    case MotionEvent.ACTION_MOVE:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_MOVE");
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_CANCEL");
                        break;
                    case MotionEvent.ACTION_OUTSIDE:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_OUTSIDE");
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_POINTER_DOWN");
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_POINTER_UP");
                        break;
                    case MotionEvent.ACTION_BUTTON_PRESS:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_BUTTON_PRESS");
                        break;
                    case MotionEvent.ACTION_BUTTON_RELEASE:
                        Log.d("按钮:", "onTouch: MotionEvent.ACTION_BUTTON_RELEASE");
                        break;
                    default:
                        break;
                }
                return true;
            }
        });

        linearLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        Log.d("父布局:", "onTouch: MotionEvent.ACTION_DOWN");
                        Log.d("父布局:点击坐标(相对控件本身):", "onTouch: x," + event.getX() + ";y," + event.getY());
                        Log.d("父布局:点击坐标(相对上层布局):", "onTouch: Left," + v.getLeft() + ";Top," + v.getTop() + ";Right," + v.getRight()
                                + ";Bottom," + v.getBottom());
                        Log.d("父布局:点击坐标(相对整个屏幕):", "onTouch: X," + event.getRawX() + ";Y," + event.getRawY());
                        break;
                    case MotionEvent.ACTION_UP:
                        Log.d("父布局:", "onTouch: MotionEvent.ACTION_UP");
                        Log.d("父布局:点击坐标(相对控件本身):", "onTouch: x," + event.getX() + ";y," + event.getY());
                        Log.d("父布局:点击坐标(相对上层布局):", "onTouch: Left," + v.getLeft() + ";Top," + v.getTop() + ";Right," + v.getRight()
                                + ";Bottom," + v.getBottom());
                        Log.d("父布局:点击坐标(相对整个屏幕):", "onTouch: X," + event.getRawX() + ";Y," + event.getRawY());
                        break;
                    case MotionEvent.ACTION_MOVE:
                        Log.d("父布局:", "onTouch: MotionEvent.ACTION_MOVE");
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        Log.d("父布局:", "onTouch: MotionEvent.ACTION_CANCEL");
                        break;
                    case MotionEvent.ACTION_OUTSIDE:
                        Log.d("父布局:", "onTouch: MotionEvent.ACTION_OUTSIDE");
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        Log.d("父布局:", "onTouch: MotionEvent.ACTION_POINTER_DOWN");
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        Log.d("父布局:", "onTouch: MotionEvent.ACTION_POINTER_UP");
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }
}

activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.hfut.operationscrollpre.MainActivity">

    <LinearLayout
        android:layout_marginLeft="100px"
        android:id="@+id/test_layout"
        android:orientation="vertical"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <Button
        android:text="我是测试按钮"
        android:id="@+id/test_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

4.2 测试结果

(1)点击屏幕

(2)滑动屏幕

(3)点击按钮

(4)滑动按钮

分析:

getX() + getLeft()+父布局到屏幕左侧距离=getRawX()

getY()+getTop()+父布局到屏幕上边距离=getRawY()

从日志来看我们的父布局(id为test_layout)到屏幕上边距离是118px,实际上我们并没有设置marginTop属性值,这里我们千万别忘了其父布局上面还有一个存放ActionBar的FrameLayout所占据的空间,还有就是我们平时喜欢使用dp单位来表示margin属性值,而这里获取的坐标单位都是px,所以在测试的时候需要注意,有时候我们设置了margin值为100dp,显示的结果大小很可能不是100px,这之间有一个单位换算。可以使用:

public static int dp2px(Context context, float dipValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dipValue * scale + 0.5f);
}

获取,首先获取像素密度,然后在换算成对应的像素值;假如我们把上面的设置改为:

<LinearLayout
    android:layout_marginLeft="100dp"
    android:id="@+id/test_layout"
    android:orientation="vertical"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<Button
    android:text="我是测试按钮"
    android:id="@+id/test_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
</LinearLayout>

再次点击子布局,日志如下:

再看看MainActivity中打印的日志:

Log.d(TAG, "onCreate: "+dp2px(getApplicationContext(),100));//代码

  08-18 10:39:58.096 9114-9114/? D/MainActivity: onCreate: 133  //日志

猜你喜欢

转载自blog.csdn.net/hfut_why/article/details/81810845
今日推荐